Browse Source

Merge branch 'refs/heads/master' into ScrmStore

# Conflicts:
#	fs-admin/src/main/resources/application.yml
#	fs-service/src/main/java/com/fs/company/service/impl/CompanyRechargeOrderServiceImpl.java
#	fs-service/src/main/java/com/fs/core/config/WxPayProperties.java
#	fs-service/src/main/resources/application-common.yml
chenguo 4 days ago
parent
commit
81b2c40f15
99 changed files with 1946 additions and 999 deletions
  1. 0 1
      .gitignore
  2. 63 0
      fs-admin/src/main/java/com/fs/company/controller/CompanyRedPackageController.java
  3. 1 8
      fs-admin/src/main/java/com/fs/course/controller/FsCourseQuestionBankController.java
  4. 1 1
      fs-admin/src/main/java/com/fs/course/controller/FsCourseRedPacketLogController.java
  5. 2 26
      fs-admin/src/main/java/com/fs/course/controller/FsUserCourseController.java
  6. 1 12
      fs-admin/src/main/java/com/fs/course/controller/FsUserCourseTrainingCampController.java
  7. 0 12
      fs-admin/src/main/java/com/fs/course/controller/FsUserCourseVideoController.java
  8. 1 14
      fs-admin/src/main/java/com/fs/course/controller/FsVideoResourceController.java
  9. 65 7
      fs-admin/src/main/java/com/fs/his/controller/FsUserController.java
  10. 18 0
      fs-admin/src/main/java/com/fs/his/controller/FsUserOnlineStateController.java
  11. 20 0
      fs-admin/src/main/java/com/fs/his/task/SendRedPacketTask.java
  12. 19 0
      fs-admin/src/main/java/com/fs/qw/OrderTask.java
  13. 1 1
      fs-admin/src/main/java/com/fs/qw/controller/QwSopController.java
  14. 18 0
      fs-common/src/main/java/com/fs/common/utils/StringUtils.java
  15. 5 1
      fs-company/pom.xml
  16. 34 0
      fs-company/src/main/java/com/fs/company/controller/company/CompanyRechargeController.java
  17. 1 1
      fs-company/src/main/java/com/fs/company/controller/course/FsCourseTrafficLogController.java
  18. 1 1
      fs-company/src/main/java/com/fs/company/controller/course/FsUserCourseController.java
  19. 8 0
      fs-company/src/main/java/com/fs/company/controller/pay/WxPayApiController.java
  20. 189 0
      fs-company/src/main/java/com/fs/company/controller/pay/WxPayController.java
  21. 98 0
      fs-company/src/main/java/com/fs/company/controller/pay/bean/AliPayBean.java
  22. 71 0
      fs-company/src/main/java/com/fs/company/controller/pay/bean/WxPayBean.java
  23. 106 0
      fs-company/src/main/java/com/fs/company/controller/pay/bean/WxPayV3Bean.java
  24. 29 2
      fs-company/src/main/java/com/fs/company/controller/store/FsUserController.java
  25. 18 0
      fs-company/src/main/java/com/fs/company/controller/store/FsUserOnlineStateController.java
  26. 1 0
      fs-company/src/main/java/com/fs/framework/config/SecurityConfig.java
  27. 7 0
      fs-company/src/main/java/com/fs/user/FsUserAdminController.java
  28. 64 0
      fs-service/src/main/java/com/fs/company/domain/CompanyRedPackage.java
  29. 18 0
      fs-service/src/main/java/com/fs/company/dto/CompBuySmsDTO.java
  30. 13 0
      fs-service/src/main/java/com/fs/company/dto/CompanyIdAndUserDTO.java
  31. 15 0
      fs-service/src/main/java/com/fs/company/dto/RechargeDTO.java
  32. 3 0
      fs-service/src/main/java/com/fs/company/mapper/CompanyMoneyLogsMapper.java
  33. 16 0
      fs-service/src/main/java/com/fs/company/service/CompanyRechargeOrderService.java
  34. 3 0
      fs-service/src/main/java/com/fs/company/service/ICompanyMoneyLogsService.java
  35. 17 0
      fs-service/src/main/java/com/fs/company/service/ICompanyRechargeService.java
  36. 6 0
      fs-service/src/main/java/com/fs/company/service/impl/CompanyMoneyLogsServiceImpl.java
  37. 4 1
      fs-service/src/main/java/com/fs/company/service/impl/CompanyRechargeOrderServiceImpl.java
  38. 61 3
      fs-service/src/main/java/com/fs/company/service/impl/CompanyRechargeServiceImpl.java
  39. 2 2
      fs-service/src/main/java/com/fs/core/config/WxOpenProperties.java
  40. 3 0
      fs-service/src/main/java/com/fs/core/config/WxPayProperties.java
  41. 1 0
      fs-service/src/main/java/com/fs/course/config/CourseConfig.java
  42. 1 1
      fs-service/src/main/java/com/fs/course/domain/FsCourseRedPacketLog.java
  43. 0 2
      fs-service/src/main/java/com/fs/course/domain/FsVideoResource.java
  44. 5 0
      fs-service/src/main/java/com/fs/course/mapper/FsCourseWatchLogMapper.java
  45. 5 7
      fs-service/src/main/java/com/fs/course/mapper/FsUserCourseMapper.java
  46. 0 3
      fs-service/src/main/java/com/fs/course/mapper/FsUserCourseVideoMapper.java
  47. 2 0
      fs-service/src/main/java/com/fs/course/param/FsUserCourseVideoAddKfUParam.java
  48. 1 1
      fs-service/src/main/java/com/fs/course/param/newfs/FsUserCourseAddCompanyUserParam.java
  49. 1 1
      fs-service/src/main/java/com/fs/course/service/IFsCourseQuestionBankService.java
  50. 1 0
      fs-service/src/main/java/com/fs/course/service/IFsCourseRedPacketLogService.java
  51. 2 2
      fs-service/src/main/java/com/fs/course/service/IFsUserCourseService.java
  52. 1 1
      fs-service/src/main/java/com/fs/course/service/IFsUserCourseTrainingCampService.java
  53. 0 1
      fs-service/src/main/java/com/fs/course/service/IFsUserCourseVideoService.java
  54. 1 2
      fs-service/src/main/java/com/fs/course/service/impl/FsCourseQuestionBankServiceImpl.java
  55. 142 0
      fs-service/src/main/java/com/fs/course/service/impl/FsCourseRedPacketLogServiceImpl.java
  56. 5 6
      fs-service/src/main/java/com/fs/course/service/impl/FsUserCourseServiceImpl.java
  57. 1 2
      fs-service/src/main/java/com/fs/course/service/impl/FsUserCourseTrainingCampServiceImpl.java
  58. 174 40
      fs-service/src/main/java/com/fs/course/service/impl/FsUserCourseVideoServiceImpl.java
  59. 15 0
      fs-service/src/main/java/com/fs/his/domain/FsUser.java
  60. 4 0
      fs-service/src/main/java/com/fs/his/service/impl/FsPackageServiceImpl.java
  61. 20 0
      fs-service/src/main/java/com/fs/his/service/impl/FsUserServiceImpl.java
  62. 2 0
      fs-service/src/main/java/com/fs/his/service/impl/FsUserWxServiceImpl.java
  63. 1 1
      fs-service/src/main/java/com/fs/sop/mapper/QwSopTagMapper.java
  64. 12 0
      fs-service/src/main/java/com/fs/statis/domain/FsStatisQwWatch.java
  65. 44 0
      fs-service/src/main/java/com/fs/wx/utils/OrderUtils.java
  66. 4 3
      fs-service/src/main/resources/application-config-druid-kyt.yml
  67. 18 0
      fs-service/src/main/resources/application-dev.yml
  68. 15 0
      fs-service/src/main/resources/application-druid-fby.yml
  69. 0 168
      fs-service/src/main/resources/application-druid-hzyy-test.yml
  70. 0 151
      fs-service/src/main/resources/application-druid-jzzx-test.yml
  71. 3 0
      fs-service/src/main/resources/application-druid-kyt.yml
  72. 0 150
      fs-service/src/main/resources/application-druid-qdtst-test.yml
  73. 0 148
      fs-service/src/main/resources/application-druid-sxjz-test.yml
  74. 12 0
      fs-service/src/main/resources/application-druid-sxjz.yml
  75. 0 153
      fs-service/src/main/resources/application-druid-xfk-test.yml
  76. 17 1
      fs-service/src/main/resources/mapper/company/CompanyMoneyLogsMapper.xml
  77. 2 7
      fs-service/src/main/resources/mapper/course/FsCourseQuestionBankMapper.xml
  78. 1 0
      fs-service/src/main/resources/mapper/course/FsCourseRedPacketLogMapper.xml
  79. 0 11
      fs-service/src/main/resources/mapper/course/FsUserCourseMapper.xml
  80. 0 3
      fs-service/src/main/resources/mapper/course/FsUserCourseTrainingCampMapper.xml
  81. 0 7
      fs-service/src/main/resources/mapper/course/FsUserCourseVideoMapper.xml
  82. 0 3
      fs-service/src/main/resources/mapper/course/FsVideoResourceMapper.xml
  83. 8 5
      fs-service/src/main/resources/mapper/his/FsStoreOrderMapper.xml
  84. 39 9
      fs-service/src/main/resources/mapper/statis/FsStatisQwWatchMapper.xml
  85. 10 0
      fs-service/src/main/resources/pay/alipay.properties
  86. 8 0
      fs-service/src/main/resources/pay/alipay1.properties
  87. BIN
      fs-service/src/main/resources/pay/cert/apiclient_cert.p12
  88. 26 0
      fs-service/src/main/resources/pay/cert/apiclient_cert.pem
  89. 28 0
      fs-service/src/main/resources/pay/cert/apiclient_key.pem
  90. 18 0
      fs-service/src/main/resources/pay/cert/证书使用说明.txt
  91. 8 0
      fs-service/src/main/resources/pay/wxpay.properties
  92. 9 0
      fs-service/src/main/resources/pay/wxpay_v3.properties
  93. 1 1
      fs-user-app/src/main/java/com/fs/app/controller/IndexController.java
  94. 12 3
      fs-user-app/src/main/java/com/fs/app/controller/UserController.java
  95. 235 0
      fs-user-app/src/main/java/com/fs/app/controller/WxH5MpController.java
  96. 9 0
      fs-user-app/src/main/java/com/fs/app/controller/WxPayController.java
  97. 1 1
      fs-user-app/src/main/java/com/fs/app/controller/course/CourseQwController.java
  98. 6 0
      fs-user-app/src/main/java/com/fs/app/param/FsUserLoginByMpParam.java
  99. 12 12
      fs-user-app/src/main/java/com/fs/framework/config/RedisConfig.java

+ 0 - 1
.gitignore

@@ -8,7 +8,6 @@ target/
 #logback.xml
 application.yml
 
-
 ### STS ###
 .apt_generated
 .classpath

+ 63 - 0
fs-admin/src/main/java/com/fs/company/controller/CompanyRedPackageController.java

@@ -0,0 +1,63 @@
+package com.fs.company.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.company.domain.*;
+import com.fs.company.service.ICompanyMoneyLogsService;
+import com.fs.company.service.ICompanyProfitLogsService;
+import com.fs.company.service.ICompanyProfitService;
+import com.fs.company.service.ICompanyService;
+import com.fs.framework.web.service.TokenService;
+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 2022-07-04
+ */
+@RestController
+@RequestMapping("/company/redPackage")
+public class CompanyRedPackageController extends BaseController
+{
+    @Autowired
+    private ICompanyMoneyLogsService moneyLogsService;
+    /**
+     * 查询提现列表
+     */
+    @PreAuthorize("@ss.hasPermi('company:redPackage:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(CompanyRedPackage companyRedPackage)
+    {
+        startPage();
+        List<CompanyRedPackage> list = moneyLogsService.selectCompanyRedPackageListVO(companyRedPackage);
+        String dateTime = companyRedPackage.getDateTime();
+        list.forEach(m -> m.setDateTime(dateTime));
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出提现列表
+     */
+    @PreAuthorize("@ss.hasPermi('company:redPackage:export')")
+    @Log(title = "提现", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(CompanyRedPackage companyRedPackage)
+    {
+        List<CompanyRedPackage> list = moneyLogsService.selectCompanyRedPackageListVO(companyRedPackage);
+        String dateTime = companyRedPackage.getDateTime();
+        list.forEach(m -> m.setDateTime(dateTime));
+        ExcelUtil<CompanyRedPackage> util = new ExcelUtil<CompanyRedPackage>(CompanyRedPackage.class);
+        return util.exportExcel(list, "红包金额记录");
+    }
+
+
+}

+ 1 - 8
fs-admin/src/main/java/com/fs/course/controller/FsCourseQuestionBankController.java

@@ -43,9 +43,6 @@ public class FsCourseQuestionBankController extends BaseController
     public TableDataInfo list(FsCourseQuestionBank fsCourseQuestionBank)
     {
         startPage();
-        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
-        Long userId = loginUser.getUser().getUserId();
-        fsCourseQuestionBank.setUserId(userId);
         List<FsCourseQuestionBank> list = fsCourseQuestionBankService.selectFsCourseQuestionBankList(fsCourseQuestionBank);
         return getDataTable(list);
     }
@@ -58,9 +55,6 @@ public class FsCourseQuestionBankController extends BaseController
     @GetMapping("/export")
     public AjaxResult export(FsCourseQuestionBank fsCourseQuestionBank)
     {
-        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
-        Long userId = loginUser.getUser().getUserId();
-        fsCourseQuestionBank.setUserId(userId);
         List<FsCourseQuestionBankImportDTO> list = fsCourseQuestionBankService.exportData(fsCourseQuestionBank);
         ExcelUtil<FsCourseQuestionBankImportDTO> util = new ExcelUtil<>(FsCourseQuestionBankImportDTO.class);
         return util.exportExcel(list, "题库数据");
@@ -87,7 +81,6 @@ public class FsCourseQuestionBankController extends BaseController
     {
         LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
         fsCourseQuestionBank.setCreateBy(loginUser.getUser().getNickName());
-        fsCourseQuestionBank.setUserId(loginUser.getUser().getUserId());
         return toAjax(fsCourseQuestionBankService.insertFsCourseQuestionBank(fsCourseQuestionBank));
     }
 
@@ -128,7 +121,7 @@ public class FsCourseQuestionBankController extends BaseController
         List<FsCourseQuestionBankImportDTO> list = util.importExcel(file.getInputStream());
 
         LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
-        String message = fsCourseQuestionBankService.importData(list, loginUser.getUser().getNickName(), loginUser.getUser().getUserId());
+        String message = fsCourseQuestionBankService.importData(list, loginUser.getUser().getNickName());
         return AjaxResult.success(message);
     }
 

+ 1 - 1
fs-admin/src/main/java/com/fs/course/controller/FsCourseRedPacketLogController.java

@@ -135,7 +135,7 @@ public class FsCourseRedPacketLogController extends BaseController
     @GetMapping("/courseList")
     public R courseList()
     {
-        List<OptionsVO> optionsVOS = fsUserCourseMapper.selectFsUserCourseAllList(null);
+        List<OptionsVO> optionsVOS = fsUserCourseMapper.selectFsUserCourseAllList();
         return R.ok().put("list", optionsVOS);
     }
 

+ 2 - 26
fs-admin/src/main/java/com/fs/course/controller/FsUserCourseController.java

@@ -44,9 +44,6 @@ public class FsUserCourseController extends BaseController
     @Autowired
     private RedisCacheUtil redisCacheUtil;
 
-    @Autowired
-    private TokenService tokenService;
-
     /**
      * 查询课程列表
      */
@@ -55,9 +52,6 @@ public class FsUserCourseController extends BaseController
     public TableDataInfo list(FsUserCourse fsUserCourse)
     {
         startPage();
-        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
-        Long userId = loginUser.getUser().getUserId();
-        fsUserCourse.setUserId(userId);
         List<FsUserCourseListPVO> list = fsUserCourseService.selectFsUserCourseListPVO(fsUserCourse);
         return getDataTable(list);
     }
@@ -70,9 +64,6 @@ public class FsUserCourseController extends BaseController
     public TableDataInfo publicList(FsUserCourse fsUserCourse)
     {
         startPage();
-        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
-        Long userId = loginUser.getUser().getUserId();
-        fsUserCourse.setUserId(userId);
         List<FsUserCourseListPVO> list = fsUserCourseService.selectFsUserCourseListPVO(fsUserCourse);
         return getDataTable(list);
     }
@@ -85,9 +76,6 @@ public class FsUserCourseController extends BaseController
     @GetMapping("/export")
     public AjaxResult export(FsUserCourse fsUserCourse)
     {
-        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
-        Long userId = loginUser.getUser().getUserId();
-        fsUserCourse.setUserId(userId);
         List<FsUserCourse> list = fsUserCourseService.selectFsUserCourseList(fsUserCourse);
         ExcelUtil<FsUserCourse> util = new ExcelUtil<FsUserCourse>(FsUserCourse.class);
         return util.exportExcel(list, "课程数据");
@@ -101,9 +89,6 @@ public class FsUserCourseController extends BaseController
     @GetMapping("/publicExport")
     public AjaxResult publicExport(FsUserCourse fsUserCourse)
     {
-        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
-        Long userId = loginUser.getUser().getUserId();
-        fsUserCourse.setUserId(userId);
         List<FsUserCourse> list = fsUserCourseService.selectFsUserCourseList(fsUserCourse);
         ExcelUtil<FsUserCourse> util = new ExcelUtil<FsUserCourse>(FsUserCourse.class);
         return util.exportExcel(list, "课程数据");
@@ -137,9 +122,6 @@ public class FsUserCourseController extends BaseController
     @PostMapping
     public AjaxResult add(@RequestBody FsUserCourse fsUserCourse)
     {
-        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
-        Long userId = loginUser.getUser().getUserId();
-        fsUserCourse.setUserId(userId);
         fsUserCourseService.insertFsUserCourse(fsUserCourse);
         redisCacheUtil.delRedisKey("getCourseList");
 
@@ -154,9 +136,6 @@ public class FsUserCourseController extends BaseController
     @PostMapping("/public")
     public AjaxResult publicAdd(@RequestBody FsUserCourse fsUserCourse)
     {
-        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
-        Long userId = loginUser.getUser().getUserId();
-        fsUserCourse.setUserId(userId);
         fsUserCourseService.insertFsUserCourse(fsUserCourse);
         redisCacheUtil.delRedisKey("getCourseList");
 
@@ -197,9 +176,7 @@ public class FsUserCourseController extends BaseController
     @GetMapping("/copy/{courseId}")
     public AjaxResult copy(@PathVariable Long courseId)
     {
-        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
-        Long userId = loginUser.getUser().getUserId();
-        int i = fsUserCourseService.copyFsUserCourse(courseId, userId);
+        int i = fsUserCourseService.copyFsUserCourse(courseId);
         return toAjax(i);
     }
 
@@ -232,8 +209,7 @@ public class FsUserCourseController extends BaseController
     @GetMapping("/getAllList")
     public R getAllList()
     {
-        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
-        List<OptionsVO> list = fsUserCourseService.selectFsUserCourseAllList(loginUser.getUser().getUserId());
+        List<OptionsVO> list = fsUserCourseService.selectFsUserCourseAllList();
         return R.ok().put("data", list);
     }
 

+ 1 - 12
fs-admin/src/main/java/com/fs/course/controller/FsUserCourseTrainingCampController.java

@@ -12,14 +12,10 @@ import com.fs.course.dto.FsUserCourseTrainingCampDTO;
 import com.fs.course.dto.FsUserCourseTrainingCampUpdateDTO;
 import com.fs.course.service.IFsUserCourseTrainingCampService;
 import com.fs.course.vo.FsUserCourseTrainingCampVO;
-import com.fs.framework.web.service.TokenService;
 import com.fs.his.vo.OptionsVO;
 import com.github.pagehelper.PageHelper;
 import com.github.pagehelper.PageInfo;
 import lombok.AllArgsConstructor;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.web.bind.annotation.*;
 
@@ -34,12 +30,8 @@ import java.util.Objects;
 @AllArgsConstructor
 public class FsUserCourseTrainingCampController {
 
-    private static final Logger log = LoggerFactory.getLogger(FsUserCourseTrainingCampController.class);
     private final IFsUserCourseTrainingCampService fsUserCourseTrainingCampService;
 
-    @Autowired
-    private TokenService tokenService;
-
     /**
      * 查询训练营列表
      */
@@ -70,10 +62,7 @@ public class FsUserCourseTrainingCampController {
     @Log(title = "训练营", businessType = BusinessType.INSERT)
     @PostMapping
     public AjaxResult add(@Valid @RequestBody FsUserCourseTrainingCampDTO params) {
-        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
-        Long userId = loginUser.getUser().getUserId();
-
-        fsUserCourseTrainingCampService.add(params, userId);
+        fsUserCourseTrainingCampService.add(params);
         return AjaxResult.success();
     }
 

+ 0 - 12
fs-admin/src/main/java/com/fs/course/controller/FsUserCourseVideoController.java

@@ -47,9 +47,6 @@ public class FsUserCourseVideoController extends BaseController
     @Autowired
     private IFsUserCourseService fsUserCourseService;
 
-    @Autowired
-    private TokenService tokenService;
-
     /**
      * 查询课堂视频列表
      */
@@ -70,9 +67,6 @@ public class FsUserCourseVideoController extends BaseController
     @GetMapping("/export")
     public AjaxResult export(FsUserCourseVideo fsUserCourseVideo)
     {
-        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
-        Long userId = loginUser.getUser().getUserId();
-        fsUserCourseVideo.setUserId(userId);
         List<FsUserCourseVideo> list = fsUserCourseVideoService.selectFsUserCourseVideoList(fsUserCourseVideo);
         ExcelUtil<FsUserCourseVideo> util = new ExcelUtil<FsUserCourseVideo>(FsUserCourseVideo.class);
         return util.exportExcel(list, "课堂视频数据");
@@ -100,9 +94,6 @@ public class FsUserCourseVideoController extends BaseController
         if (count>0){
             return AjaxResult.error("课程排序重复");
         }
-        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
-        Long userId = loginUser.getUser().getUserId();
-        fsUserCourseVideo.setUserId(userId);
 
         // 设置项目ID
         FsUserCourse fsUserCourse = fsUserCourseService.selectFsUserCourseByCourseId(fsUserCourseVideo.getCourseId());
@@ -137,9 +128,6 @@ public class FsUserCourseVideoController extends BaseController
     public TableDataInfo getVideoListByCourseId(FsUserCourseVideo fsUserCourseVideo)
     {
         startPage();
-        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
-        Long userId = loginUser.getUser().getUserId();
-        fsUserCourseVideo.setUserId(userId);
         List<FsUserCourseVideo> list = fsUserCourseVideoService.selectFsUserCourseVideoListByCourseId(fsUserCourseVideo);
         return getDataTable(list);
     }

+ 1 - 14
fs-admin/src/main/java/com/fs/course/controller/FsVideoResourceController.java

@@ -33,9 +33,6 @@ public class FsVideoResourceController extends BaseController {
 
     private final IFsVideoResourceService fsVideoResourceService;
 
-    @Autowired
-    private TokenService tokenService;
-
     /**
      * 查询视频素材库列表
      */
@@ -53,8 +50,6 @@ public class FsVideoResourceController extends BaseController {
         params.put("fileName", fileName);
         params.put("typeId", typeId);
         params.put("typeSubId", typeSubId);
-        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
-        params.put("userId", loginUser.getUser().getUserId());
 
         PageHelper.startPage(pageNum, pageSize);
         List<FsVideoResourceVO> list = fsVideoResourceService.selectVideoResourceListByMap(params);
@@ -80,9 +75,6 @@ public class FsVideoResourceController extends BaseController {
     @PostMapping
     public AjaxResult add(@RequestBody FsVideoResource fsVideoResource)
     {
-        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
-        Long userId = loginUser.getUser().getUserId();
-        fsVideoResource.setUserId(userId);
         fsVideoResource.setCreateTime(LocalDateTime.now());
         fsVideoResourceService.save(fsVideoResource);
         return AjaxResult.success();
@@ -156,15 +148,10 @@ public class FsVideoResourceController extends BaseController {
     @Log(title = "视频素材库", businessType = BusinessType.INSERT)
     @PostMapping("/batchAddVideoResource")
     public AjaxResult batchAddVideoResource(@RequestBody List<FsVideoResource> list) {
-        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
-        Long userId = loginUser.getUser().getUserId();
         if (Objects.isNull(list) || list.isEmpty()) {
             return AjaxResult.error("数据不能为空");
         }
-        list.forEach(v -> {
-            v.setCreateTime(LocalDateTime.now());
-            v.setUserId(userId);
-        });
+        list.forEach(v -> v.setCreateTime(LocalDateTime.now()));
         fsVideoResourceService.saveBatch(list);
         return AjaxResult.success();
     }

+ 65 - 7
fs-admin/src/main/java/com/fs/his/controller/FsUserController.java

@@ -1,9 +1,7 @@
 package com.fs.his.controller;
 
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
+import java.util.*;
+import java.util.stream.Collectors;
 
 import com.alibaba.fastjson.JSON;
 import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
@@ -13,9 +11,12 @@ import com.fs.common.exception.CustomException;
 import com.fs.common.utils.ParseUtils;
 import com.fs.common.utils.SecurityUtils;
 import com.fs.common.utils.StringUtils;
+import com.fs.course.domain.FsUserWatchStatistics;
+import com.fs.course.mapper.FsUserWatchStatisticsMapper;
 import com.fs.course.service.IFsUserCompanyUserService;
 import com.fs.his.domain.FsUserAddress;
 import com.fs.his.enums.FsUserIntegralLogTypeEnum;
+import com.fs.his.mapper.FsUserMapper;
 import com.fs.his.param.FsUserAddIntegralTemplateParam;
 import com.fs.his.param.FsUserAddPointsParam;
 import com.fs.his.param.FsUserParam;
@@ -29,8 +30,12 @@ import com.fs.store.param.h5.FsUserPageListParam;
 import com.fs.store.vo.h5.FsUserPageListVO;
 import com.github.pagehelper.PageHelper;
 import com.github.pagehelper.PageInfo;
+import com.google.common.collect.Lists;
 import io.swagger.annotations.ApiOperation;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.ibatis.session.ExecutorType;
+import org.apache.ibatis.session.SqlSession;
+import org.apache.ibatis.session.SqlSessionFactory;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.validation.annotation.Validated;
@@ -71,6 +76,9 @@ public class FsUserController extends BaseController
     @Autowired
     private IFsUserCompanyUserService userCompanyUserService;
 
+    @Autowired
+    private SqlSessionFactory sqlSessionFactory;
+
     /**
      * 查询用户列表
      */
@@ -82,6 +90,9 @@ public class FsUserController extends BaseController
         if (fsUser.getPhoneMk()!=null&&fsUser.getPhoneMk()!=""){
             fsUser.setPhone(encryptPhone(fsUser.getPhoneMk()));
         }
+        if(StringUtils.isNotEmpty(fsUser.getPhone())){
+            fsUser.setPhone(encryptPhone(fsUser.getPhone()));
+        }
         List<FsUserVO> list = fsUserService.selectFsUserListVO(fsUser);
         for (FsUserVO fsUserVO : list) {
             if(fsUserVO.getPhone() != null&&fsUserVO.getPhone()!=""){
@@ -241,10 +252,11 @@ public class FsUserController extends BaseController
     public R darkRoomList(FsUserPageListParam param) {
 //        startPage();
 //        PageHelper.startPage(param.getPageNum(), param.getPageSize());
-        PageInfo<FsUserPageListVO> fsUserPageListVOPageInfo = fsUserService.selectFsUserPageList(param);
-        for (FsUserPageListVO fsUserPageListVO : fsUserPageListVOPageInfo.getList()) {
-            fsUserPageListVO.setPhone(ParseUtils.parsePhone(fsUserPageListVO.getPhone()));
+        //判断是否是电话号码
+        if(StringUtils.isFullNumber(param.getKeyword()) && param.getKeyword().trim().length() == 11){
+            param.setKeyword(encryptPhone(param.getKeyword()));
         }
+        PageInfo<FsUserPageListVO> fsUserPageListVOPageInfo = fsUserService.selectFsUserPageList(param);
         Map<String, Object> map = new HashMap<String, Object>();
         map.put("rows", fsUserPageListVOPageInfo.getList());
         map.put("total", fsUserPageListVOPageInfo.getTotal());
@@ -260,6 +272,30 @@ public class FsUserController extends BaseController
         return ResponseResult.ok(r);
     }
 
+    @PreAuthorize("@ss.hasPermi('his:user:blacklist')")
+    @GetMapping("/blacklist")
+    @ApiOperation("黑名单")
+    public R blacklist(FsUserPageListParam param) {
+        //判断是否是电话号码
+        if(StringUtils.isFullNumber(param.getKeyword()) && param.getKeyword().trim().length() == 11){
+            param.setKeyword(encryptPhone(param.getKeyword()));
+        }
+        PageInfo<FsUserPageListVO> fsUserPageListVOPageInfo = fsUserService.selectFsUserPageList(param);
+        Map<String, Object> map = new HashMap<String, Object>();
+        map.put("rows", fsUserPageListVOPageInfo.getList());
+        map.put("total", fsUserPageListVOPageInfo.getTotal());
+        return R.ok(map);
+    }
+
+    @PreAuthorize("@ss.hasPermi('his:user:enabledBlackUsers')")
+    @PostMapping("/enabledBlackUsers")
+    @ApiOperation("批量启用会员")
+    public ResponseResult<Boolean> enabledBlackUsers(@RequestBody List<UserProjectDTO> ids) {
+        log.debug("批量启用会员 ids: {}", JSON.toJSONString(ids));
+        Boolean r = userCompanyUserService.batchUpdateUserProjectStatus(ids, 1);
+        return ResponseResult.ok(r);
+    }
+
     @PreAuthorize("@ss.hasPermi('his:user:addPoints')")
     @PostMapping("/addPoints")
     @ApiOperation("添加积分")
@@ -273,4 +309,26 @@ public class FsUserController extends BaseController
         return userIntegralLogsService.addIntegralTemplate(integralTemplateParam);
     }
 
+//    @PutMapping("/encryptPhoneTemp")
+//    @ApiOperation("临时接口")
+//    public void encryptPhoneTemp(){
+//        FsUser fsUser = new FsUser();
+//        List<FsUser> list = fsUserService.selectFsUserList(fsUser);
+//        List<FsUser> fsUserList = list.stream().peek(v -> v.setPhone(encryptPhone(v.getPhone()))).collect(Collectors.toList());
+//
+//        // 分批次处理,一次提交500条
+//        List<List<FsUser>> batches = Lists.partition(fsUserList, 500);
+//        batches.forEach(batch -> {
+//            SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
+//            try {
+//                FsUserMapper mapper = sqlSession.getMapper(FsUserMapper.class);
+//                batch.forEach(mapper::updateFsUser);
+//                sqlSession.commit();
+//            } finally {
+//                sqlSession.close();
+//            }
+//        });
+//
+//    }
+
 }

+ 18 - 0
fs-admin/src/main/java/com/fs/his/controller/FsUserOnlineStateController.java

@@ -5,6 +5,7 @@ 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.StringUtils;
 import com.fs.common.utils.poi.ExcelUtil;
 import com.fs.his.domain.FsUserOnlineState;
 import com.fs.his.service.IFsUserOnlineStateService;
@@ -14,6 +15,9 @@ import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.web.bind.annotation.*;
 import java.util.List;
 
+import static com.fs.his.utils.PhoneUtil.decryptPhoneMk;
+import static com.fs.his.utils.PhoneUtil.encryptPhone;
+
 /**
  * 用户上线情况Controller
  *
@@ -35,7 +39,21 @@ public class FsUserOnlineStateController extends BaseController
     public TableDataInfo list(FsUserOnlineState fsUserOnlineState)
     {
         startPage();
+        if(StringUtils.isNotEmpty(fsUserOnlineState.getPhone())){
+            fsUserOnlineState.setPhone(encryptPhone(fsUserOnlineState.getPhone()));
+        }
         List<FsUserOnlineState> list = fsUserOnlineStateService.selectFsUserOnlineStateList(fsUserOnlineState);
+        if(!list.isEmpty()){
+            for (FsUserOnlineState userOnlineState : list) {
+                if(userOnlineState.getPhone() != null && userOnlineState.getPhone() != ""){
+                    if (userOnlineState.getPhone().length()>11){
+                        userOnlineState.setPhone(decryptPhoneMk(userOnlineState.getPhone()));
+                    }else {
+                        userOnlineState.setPhone(userOnlineState.getPhone().replaceAll("(\\d{3})\\d*(\\d{4})", "$1****$2"));
+                    }
+                }
+            }
+        }
         return getDataTable(list);
     }
 

+ 20 - 0
fs-admin/src/main/java/com/fs/his/task/SendRedPacketTask.java

@@ -0,0 +1,20 @@
+package com.fs.his.task;
+
+import com.fs.course.service.IFsCourseRedPacketLogService;
+import com.fs.course.service.IFsUserCourseVideoRedPackageService;
+import com.fs.course.service.IFsUserCourseVideoService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+@Slf4j
+@Service("sendRedPacketTask")
+public class SendRedPacketTask {
+    @Autowired
+    private IFsCourseRedPacketLogService redPacketLogService;
+
+    public void sendRedPacket(){
+        redPacketLogService.sendRedPacketBf();
+    }
+
+}

+ 19 - 0
fs-admin/src/main/java/com/fs/qw/OrderTask.java

@@ -0,0 +1,19 @@
+package com.fs.qw;
+
+import com.fs.company.service.CompanyRechargeOrderService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+@Component("orderTask")
+public class OrderTask {
+    @Autowired
+    private CompanyRechargeOrderService companyRechargeOrderService;
+
+
+    /**
+     * 自动关闭超时订单
+     */
+    public void autoCloseTimeOutOrder(){
+        companyRechargeOrderService.autoClosedOrder();
+    }
+}

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

@@ -77,7 +77,7 @@ public class QwSopController extends BaseController
     @GetMapping("/courseList")
     public R courseList()
     {
-        List<OptionsVO> optionsVOS = fsUserCourseMapper.selectFsUserCourseAllList(null);
+        List<OptionsVO> optionsVOS = fsUserCourseMapper.selectFsUserCourseAllList();
         return R.ok().put("list", optionsVOS);
     }
 

+ 18 - 0
fs-common/src/main/java/com/fs/common/utils/StringUtils.java

@@ -532,4 +532,22 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils
     {
         return (T) obj;
     }
+
+    /**
+     * 判断字符串是否是纯数字,true-是;false-否
+     * @param str
+     * @return
+     */
+    public static boolean isFullNumber(String str) {
+        if (str == null) {
+            return false;
+        }
+        for (char s : str.toCharArray ()) {
+            if (!Character.isDigit(s)) {
+                return false;
+            }
+        }
+        return true;
+    }
+
 }

+ 5 - 1
fs-company/pom.xml

@@ -39,7 +39,11 @@
             <version>1.9.3</version>
         </dependency>
 
-
+        <dependency>
+            <groupId>com.github.javen205</groupId>
+            <artifactId>IJPay-All</artifactId>
+            <version>2.7.8</version>
+        </dependency>
         <!-- Mysql驱动包 -->
         <dependency>
             <groupId>mysql</groupId>

+ 34 - 0
fs-company/src/main/java/com/fs/company/controller/company/CompanyRechargeController.java

@@ -11,6 +11,8 @@ import com.fs.common.utils.ServletUtils;
 import com.fs.common.utils.poi.ExcelUtil;
 import com.fs.company.domain.Company;
 import com.fs.company.domain.CompanyRecharge;
+import com.fs.company.domain.CompanyRechargeOrder;
+import com.fs.company.dto.RechargeDTO;
 import com.fs.company.service.ICompanyRechargeService;
 import com.fs.company.service.ICompanyService;
 import com.fs.company.util.OrderUtils;
@@ -72,6 +74,38 @@ public class CompanyRechargeController extends BaseController
     }
 
 
+    /**
+     * 充值
+     * @return AjaxResult
+     */
+    @PostMapping("/wxRecharge")
+    public AjaxResult recharge(@RequestBody RechargeDTO dto){
+        CompanyRechargeOrder companyRechargeOrder;
+        try {
+            LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+
+            dto.setCompanyId(loginUser.getCompany().getCompanyId());
+            dto.setUserId(loginUser.getUser().getUserId());
+            companyRechargeOrder = companyRechargeService.recharge(dto);
+        }catch (Exception e) {
+            logger.error("给公司充值失败",e);
+            return AjaxResult.error(e.getMessage());
+        }
+        return AjaxResult.success(companyRechargeOrder);
+    }
+
+    /**
+     * 查询订单
+     * @param orderNo 订单号
+     * @return AjaxResult
+     */
+    @GetMapping("/queryOrder")
+    public AjaxResult queryOrder(@RequestParam("orderNo") String orderNo) {
+        CompanyRechargeOrder order = companyRechargeService.queryOrder(orderNo);
+
+        return AjaxResult.success(order);
+    }
+
 
     /**
      * 新增充值

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

@@ -124,7 +124,7 @@ public class FsCourseTrafficLogController extends BaseController
     @GetMapping("/courseList")
     public R courseList()
     {
-        List<OptionsVO> optionsVOS = fsUserCourseMapper.selectFsUserCourseAllList(null);
+        List<OptionsVO> optionsVOS = fsUserCourseMapper.selectFsUserCourseAllList();
         return R.ok().put("list", optionsVOS);
     }
 }

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

@@ -78,7 +78,7 @@ public class FsUserCourseController extends BaseController
     @GetMapping("/getAllList")
     public R getAllList()
     {
-        List<OptionsVO> list = fsUserCourseService.selectFsUserCourseAllList(null);
+        List<OptionsVO> list = fsUserCourseService.selectFsUserCourseAllList();
         return R.ok().put("data", list);
     }
 

+ 8 - 0
fs-company/src/main/java/com/fs/company/controller/pay/WxPayApiController.java

@@ -0,0 +1,8 @@
+package com.fs.company.controller.pay;
+
+
+import com.ijpay.wxpay.WxPayApiConfig;
+
+public abstract class WxPayApiController {
+	public abstract WxPayApiConfig getApiConfig();
+}

+ 189 - 0
fs-company/src/main/java/com/fs/company/controller/pay/WxPayController.java

@@ -0,0 +1,189 @@
+package com.fs.company.controller.pay;
+
+
+import com.fs.common.core.domain.R;
+import com.fs.common.utils.StringUtils;
+import com.fs.company.controller.pay.bean.WxPayBean;
+import com.fs.company.domain.CompanyRecharge;
+import com.fs.company.service.ICompanyRechargeService;
+import com.fs.core.config.WxPayProperties;
+import com.github.binarywang.wxpay.util.SignUtils;
+import com.ijpay.core.enums.SignType;
+import com.ijpay.core.enums.TradeType;
+import com.ijpay.core.kit.HttpKit;
+import com.ijpay.core.kit.IpKit;
+import com.ijpay.core.kit.WxPayKit;
+import com.ijpay.wxpay.WxPayApi;
+import com.ijpay.wxpay.WxPayApiConfig;
+import com.ijpay.wxpay.WxPayApiConfigKit;
+import com.ijpay.wxpay.model.UnifiedOrderModel;
+import io.swagger.annotations.ApiParam;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletRequest;
+import java.math.BigDecimal;
+import java.util.HashMap;
+import java.util.Map;
+
+@Controller
+@RequestMapping(value="/pay/wxPay")
+public class WxPayController extends WxPayApiController {
+
+    private final Logger log = LoggerFactory.getLogger(this.getClass());
+
+    @Autowired
+    WxPayBean wxPayBean;
+
+    private String notifyUrl;
+    private String refundNotifyUrl;
+
+    @Autowired
+    ICompanyRechargeService rechargeService;
+
+    @Autowired
+    private WxPayProperties wxPayProperties;
+
+
+    @Override
+    public WxPayApiConfig getApiConfig() {
+        WxPayApiConfig apiConfig;
+
+        try {
+            apiConfig = WxPayApiConfigKit.getApiConfig(wxPayBean.getAppId());
+        } catch (Exception e) {
+            apiConfig = WxPayApiConfig.builder()
+                    .appId(wxPayBean.getAppId())
+                    .mchId(wxPayBean.getMchId())
+                    .partnerKey(wxPayBean.getPartnerKey())
+                    .certPath(wxPayBean.getCertPath())
+                    .domain(wxPayBean.getDomain())
+                    .build();
+        }
+        notifyUrl = apiConfig.getDomain().concat("/pay/wxPay/payNotify");
+        refundNotifyUrl = apiConfig.getDomain().concat("/pay/wxPay/refundNotify");
+        return apiConfig;
+    }
+    @GetMapping("/test")
+    @ResponseBody
+    public WxPayBean test() {
+        return wxPayBean;
+    }
+
+    @GetMapping(value="/qrPay")
+    @ResponseBody
+    public R qrPay(
+            @ApiParam(required = true, name = "orderNo", value = "订单ID") @RequestParam(value = "orderNo", required = false) String orderNo,
+            @ApiParam(required = true, name = "orderType", value = "订单类型 1 充值") @RequestParam(value = "orderType", required = false) Integer orderType,
+            HttpServletRequest request){
+        if(orderType.equals(1)){
+            CompanyRecharge recharge=rechargeService.selectCompanyRechargeByNo(orderNo);
+            if(recharge==null){
+                return R.error("充值订单不存在");
+            }
+            if(recharge.getStatus()!=0){
+                return R.error("此订单已支付");
+            }
+            Integer money= recharge.getMoney().multiply(new BigDecimal(100)).intValue();
+            String ip = IpKit.getRealIp(request);
+            if (StringUtils.isEmpty(ip)) {
+                ip = "127.0.0.1";
+            }
+            WxPayApiConfig wxPayApiConfig = WxPayApiConfigKit.getWxPayApiConfig();
+            Map<String, String> params = UnifiedOrderModel
+                    .builder()
+                    .appid(wxPayApiConfig.getAppId())
+                    .mch_id(wxPayApiConfig.getMchId())
+                    .nonce_str(WxPayKit.generateStr())
+                    .body("充值订单")
+                    .out_trade_no("recharge-"+recharge.getRechargeNo())
+                    .total_fee(money.toString())
+                    .spbill_create_ip(ip)
+                    .notify_url(notifyUrl)
+                    .trade_type(TradeType.NATIVE.getTradeType())
+                    .build()
+                    .createSign(wxPayApiConfig.getPartnerKey(), SignType.HMACSHA256);
+
+            String xmlResult = WxPayApi.pushOrder(false, params);
+            log.info("统一下单:" + xmlResult);
+
+            Map<String, String> result = WxPayKit.xmlToMap(xmlResult);
+
+            String returnCode = result.get("return_code");
+            String returnMsg = result.get("return_msg");
+            System.out.println(returnMsg);
+            if (!WxPayKit.codeIsOk(returnCode)) {
+                return R.error("error:" + returnMsg);
+            }
+            String resultCode = result.get("result_code");
+            if (!WxPayKit.codeIsOk(resultCode)) {
+                return R.error("error:" + returnMsg);
+            }
+            //生成预付订单success
+            //生成预付订单success
+            String qrCodeUrl = result.get("code_url");
+//            String name = order.getOrderNo()+".png";
+//            String filePath = FSConfig.getUploadPath();
+//            boolean encode = QrCodeKit.encode(qrCodeUrl, BarcodeFormat.QR_CODE, 3, ErrorCorrectionLevel.H, "png", 200, 200,
+//                    filePath +"/"+ File.separator + name);
+//            if (encode) {
+//                //在页面上显示
+//                order.setPayType(1);
+//                goodsOrderService.updateFsGoodsOrder(order);
+//                return R.ok().put("name",name);
+//            }
+            recharge.setPayType(1);
+            rechargeService.updateCompanyRecharge(recharge);
+            return R.ok().put("qr",qrCodeUrl);
+
+        }
+        return R.error("订单类型不正确");
+    }
+
+    @RequestMapping(value = "/payNotify",method={RequestMethod.POST, RequestMethod.GET})
+    @ResponseBody
+    public String payNotify(HttpServletRequest request) {
+        // 支付结果通用通知文档: https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_7
+        String xmlMsg = HttpKit.readData(request);
+        log.info("支付通知 {}", xmlMsg);
+        Map<String, String> params = WxPayKit.xmlToMap(xmlMsg);
+        String returnCode = params.get("return_code");
+        // 微信支付订单号
+        String transaction_id = params.get("transaction_id");
+        // 商户订单号
+        String out_trade_no = params.get("out_trade_no");
+        // 注意重复通知的情况,同一订单号可能收到多次通知,请注意一定先判断订单状态
+        // 注意此处签名方式需与统一下单的签名类型一致1
+        if (SignUtils.checkSign(params, String.valueOf(SignType.HMACSHA256), wxPayProperties.getMchKey())) {
+            if (WxPayKit.codeIsOk(returnCode)) {
+                // 更新订单信息
+                // 发送通知等
+                String[] order=out_trade_no.split("-");
+                R r;
+                if (order[0].equals("recharge")) {
+                    r = rechargeService.payNotify(order[1],transaction_id);
+                    if (r.get("code").equals(200)) {
+                        Map<String, String> xml = new HashMap<String, String>(2);
+                        xml.put("return_code", "SUCCESS");
+                        xml.put("return_msg", "OK");
+                        return WxPayKit.toXml(xml);
+
+                    } else {
+                        return null;
+                    }
+                }
+            }
+        }
+        return null;
+
+    }
+
+
+
+
+
+
+}

+ 98 - 0
fs-company/src/main/java/com/fs/company/controller/pay/bean/AliPayBean.java

@@ -0,0 +1,98 @@
+package com.fs.company.controller.pay.bean;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.PropertySource;
+import org.springframework.stereotype.Component;
+
+@Component
+@PropertySource("classpath:/pay/alipay.properties")
+@ConfigurationProperties(prefix = "alipay")
+public class AliPayBean {
+    private String appId;
+    private String privateKey;
+    private String publicKey;
+    private String appCertPath;
+    private String aliPayCertPath;
+    private String aliPayRootCertPath;
+    private String serverUrl;
+    private String domain;
+
+    public String getAppId() {
+        return appId;
+    }
+
+    public void setAppId(String appId) {
+        this.appId = appId;
+    }
+
+    public String getPrivateKey() {
+        return privateKey;
+    }
+
+    public void setPrivateKey(String privateKey) {
+        this.privateKey = privateKey;
+    }
+
+    public String getPublicKey() {
+        return publicKey;
+    }
+
+    public void setPublicKey(String publicKey) {
+        this.publicKey = publicKey;
+    }
+
+    public String getAppCertPath() {
+        return appCertPath;
+    }
+
+    public void setAppCertPath(String appCertPath) {
+        this.appCertPath = appCertPath;
+    }
+
+    public String getAliPayCertPath() {
+        return aliPayCertPath;
+    }
+
+    public void setAliPayCertPath(String aliPayCertPath) {
+        this.aliPayCertPath = aliPayCertPath;
+    }
+
+    public String getAliPayRootCertPath() {
+        return aliPayRootCertPath;
+    }
+
+    public void setAliPayRootCertPath(String aliPayRootCertPath) {
+        this.aliPayRootCertPath = aliPayRootCertPath;
+    }
+
+    public String getServerUrl() {
+        return serverUrl;
+    }
+
+    public void setServerUrl(String serverUrl) {
+        this.serverUrl = serverUrl;
+    }
+
+
+    public String getDomain() {
+        return domain;
+    }
+
+    public void setDomain(String domain) {
+        this.domain = domain;
+    }
+
+    @Override
+    public String toString() {
+        return "AliPayBean{" +
+                "appId='" + appId + '\'' +
+                ", privateKey='" + privateKey + '\'' +
+                ", publicKey='" + publicKey + '\'' +
+                ", appCertPath='" + appCertPath + '\'' +
+                ", aliPayCertPath='" + aliPayCertPath + '\'' +
+                ", aliPayRootCertPath='" + aliPayRootCertPath + '\'' +
+                ", serverUrl='" + serverUrl + '\'' +
+                ", domain='" + domain + '\'' +
+                '}';
+    }
+}

+ 71 - 0
fs-company/src/main/java/com/fs/company/controller/pay/bean/WxPayBean.java

@@ -0,0 +1,71 @@
+package com.fs.company.controller.pay.bean;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.PropertySource;
+import org.springframework.stereotype.Component;
+
+@Component
+@PropertySource("classpath:/pay/wxpay.properties")
+@ConfigurationProperties(prefix = "wxpay")
+public class WxPayBean {
+    private String appId;
+    private String appSecret;
+    private String mchId;
+    private String partnerKey;
+    private String certPath;
+    private String domain;
+
+    public String getAppId() {
+        return appId;
+    }
+
+    public void setAppId(String appId) {
+        this.appId = appId;
+    }
+
+    public String getAppSecret() {
+        return appSecret;
+    }
+
+    public void setAppSecret(String appSecret) {
+        this.appSecret = appSecret;
+    }
+
+    public String getMchId() {
+        return mchId;
+    }
+
+    public void setMchId(String mchId) {
+        this.mchId = mchId;
+    }
+
+    public String getPartnerKey() {
+        return partnerKey;
+    }
+
+    public void setPartnerKey(String partnerKey) {
+        this.partnerKey = partnerKey;
+    }
+
+    public String getCertPath() {
+        return certPath;
+    }
+
+    public void setCertPath(String certPath) {
+        this.certPath = certPath;
+    }
+
+    public String getDomain() {
+        return domain;
+    }
+
+    public void setDomain(String domain) {
+        this.domain = domain;
+    }
+
+    @Override
+    public String toString() {
+        return "WxPayBean [appId=" + appId + ", appSecret=" + appSecret + ", mchId=" + mchId + ", partnerKey="
+                + partnerKey + ", certPath=" + certPath + ", domain=" + domain + "]";
+    }
+}

+ 106 - 0
fs-company/src/main/java/com/fs/company/controller/pay/bean/WxPayV3Bean.java

@@ -0,0 +1,106 @@
+package com.fs.company.controller.pay.bean;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.PropertySource;
+import org.springframework.stereotype.Component;
+
+@Component
+@PropertySource("classpath:/pay/wxpay_v3.properties")
+@ConfigurationProperties(prefix = "v3")
+public class WxPayV3Bean {
+    private String appId;
+    private String keyPath;
+    private String certPath;
+    private String certP12Path;
+    private String platformCertPath;
+    private String mchId;
+    private String apiKey;
+    private String apiKey3;
+    private String domain;
+
+    public String getAppId() {
+        return appId;
+    }
+
+    public void setAppId(String appId) {
+        this.appId = appId;
+    }
+
+    public String getKeyPath() {
+        return keyPath;
+    }
+
+    public void setKeyPath(String keyPath) {
+        this.keyPath = keyPath;
+    }
+
+    public String getCertPath() {
+        return certPath;
+    }
+
+    public void setCertPath(String certPath) {
+        this.certPath = certPath;
+    }
+
+    public String getCertP12Path() {
+        return certP12Path;
+    }
+
+    public void setCertP12Path(String certP12Path) {
+        this.certP12Path = certP12Path;
+    }
+
+    public String getPlatformCertPath() {
+        return platformCertPath;
+    }
+
+    public void setPlatformCertPath(String platformCertPath) {
+        this.platformCertPath = platformCertPath;
+    }
+
+    public String getMchId() {
+        return mchId;
+    }
+
+    public void setMchId(String mchId) {
+        this.mchId = mchId;
+    }
+
+    public String getApiKey() {
+        return apiKey;
+    }
+
+    public void setApiKey(String apiKey) {
+        this.apiKey = apiKey;
+    }
+
+    public String getApiKey3() {
+        return apiKey3;
+    }
+
+    public void setApiKey3(String apiKey3) {
+        this.apiKey3 = apiKey3;
+    }
+
+    public String getDomain() {
+        return domain;
+    }
+
+    public void setDomain(String domain) {
+        this.domain = domain;
+    }
+
+    @Override
+    public String toString() {
+        return "WxPayV3Bean{" +
+                "keyPath='" + keyPath + '\'' +
+                ", certPath='" + certPath + '\'' +
+                ", certP12Path='" + certP12Path + '\'' +
+                ", platformCertPath='" + platformCertPath + '\'' +
+                ", mchId='" + mchId + '\'' +
+                ", apiKey='" + apiKey + '\'' +
+                ", apiKey3='" + apiKey3 + '\'' +
+                ", domain='" + domain + '\'' +
+                '}';
+    }
+}

+ 29 - 2
fs-company/src/main/java/com/fs/company/controller/store/FsUserController.java

@@ -9,6 +9,7 @@ import com.fs.common.core.domain.ResponseResult;
 import com.fs.common.core.page.TableDataInfo;
 import com.fs.common.enums.BusinessType;
 import com.fs.common.utils.ServletUtils;
+import com.fs.common.utils.StringUtils;
 import com.fs.common.utils.poi.ExcelUtil;
 import com.fs.course.service.IFsUserCompanyUserService;
 import com.fs.framework.security.LoginUser;
@@ -241,8 +242,9 @@ public class FsUserController extends BaseController
     public R darkRoomList(FsUserPageListParam param) {
         LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
         param.setUserId(loginUser.getUser().getUserId());
-//        startPage();
-//        PageHelper.startPage(param.getPageNum(), param.getPageSize());
+        if(StringUtils.isFullNumber(param.getKeyword()) && param.getKeyword().trim().length() == 11){
+            param.setKeyword(encryptPhone(param.getKeyword()));
+        }
         PageInfo<FsUserPageListVO> fsUserPageListVOPageInfo = fsUserService.selectFsUserPageList(param);
         Map<String, Object> map = new HashMap<String, Object>();
         map.put("rows", fsUserPageListVOPageInfo.getList());
@@ -259,4 +261,29 @@ public class FsUserController extends BaseController
         return ResponseResult.ok(r);
     }
 
+    @PreAuthorize("@ss.hasPermi('users:user:blacklist')")
+    @GetMapping("/blacklist")
+    @ApiOperation("黑名单")
+    public R blacklist(FsUserPageListParam param) {
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        param.setUserId(loginUser.getUser().getUserId());
+        if(StringUtils.isFullNumber(param.getKeyword()) && param.getKeyword().trim().length() == 11){
+            param.setKeyword(encryptPhone(param.getKeyword()));
+        }
+        PageInfo<FsUserPageListVO> fsUserPageListVOPageInfo = fsUserService.selectFsUserPageList(param);
+        Map<String, Object> map = new HashMap<String, Object>();
+        map.put("rows", fsUserPageListVOPageInfo.getList());
+        map.put("total", fsUserPageListVOPageInfo.getTotal());
+        return R.ok(map);
+    }
+
+    @PreAuthorize("@ss.hasPermi('users:user:enabledBlackUsers')")
+    @PostMapping("/enabledBlackUsers")
+    @ApiOperation("批量启用会员")
+    public ResponseResult<Boolean> enabledBlackUsers(@RequestBody List<UserProjectDTO> ids) {
+        log.debug("批量启用会员 ids: {}", JSON.toJSONString(ids));
+        Boolean r = userCompanyUserService.batchUpdateUserProjectStatus(ids, 1);
+        return ResponseResult.ok(r);
+    }
+
 }

+ 18 - 0
fs-company/src/main/java/com/fs/company/controller/store/FsUserOnlineStateController.java

@@ -6,6 +6,7 @@ import com.fs.common.core.domain.AjaxResult;
 import com.fs.common.core.page.TableDataInfo;
 import com.fs.common.enums.BusinessType;
 import com.fs.common.utils.ServletUtils;
+import com.fs.common.utils.StringUtils;
 import com.fs.common.utils.poi.ExcelUtil;
 import com.fs.framework.security.LoginUser;
 import com.fs.framework.service.TokenService;
@@ -17,6 +18,9 @@ import org.springframework.web.bind.annotation.*;
 
 import java.util.List;
 
+import static com.fs.his.utils.PhoneUtil.decryptPhoneMk;
+import static com.fs.his.utils.PhoneUtil.encryptPhone;
+
 /**
  * 用户上线情况Controller
  *
@@ -48,7 +52,21 @@ public class FsUserOnlineStateController extends BaseController
         } else{
             fsUserOnlineState.setCompanyUserId( loginUser.getUser().getUserId());
         }
+        if(StringUtils.isNotEmpty(fsUserOnlineState.getPhone())){
+            fsUserOnlineState.setPhone(encryptPhone(fsUserOnlineState.getPhone()));
+        }
         List<FsUserOnlineState> list = fsUserOnlineStateService.selectFsUserOnlineStateList(fsUserOnlineState);
+        if(!list.isEmpty()){
+            for (FsUserOnlineState userOnlineState : list) {
+                if(userOnlineState.getPhone() != null && userOnlineState.getPhone() != ""){
+                    if (userOnlineState.getPhone().length()>11){
+                        userOnlineState.setPhone(decryptPhoneMk(userOnlineState.getPhone()));
+                    }else {
+                        userOnlineState.setPhone(userOnlineState.getPhone().replaceAll("(\\d{3})\\d*(\\d{4})", "$1****$2"));
+                    }
+                }
+            }
+        }
         return getDataTable(list);
     }
 

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

@@ -119,6 +119,7 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter
                 .antMatchers("/msg").anonymous()
                 .antMatchers("/common/getId**").anonymous()
                 .antMatchers("/common/uploadOSS**").anonymous()
+                .antMatchers("/pay/wxPay/payNotify**").anonymous()
                 .antMatchers("/common/uploadWang**").anonymous()
                 .antMatchers("/common/download**").anonymous()
                 .antMatchers("/common/download/resource**").anonymous()

+ 7 - 0
fs-company/src/main/java/com/fs/user/FsUserAdminController.java

@@ -8,12 +8,14 @@ import com.fs.common.core.domain.R;
 import com.fs.common.core.page.TableDataInfo;
 import com.fs.common.enums.BusinessType;
 import com.fs.common.utils.ServletUtils;
+import com.fs.common.utils.StringUtils;
 import com.fs.company.cache.ICompanyUserCacheService;
 import com.fs.framework.security.LoginUser;
 import com.fs.framework.service.TokenService;
 
 import com.fs.his.domain.FsUser;
 import com.fs.his.service.IFsUserService;
+import com.fs.his.utils.PhoneUtil;
 import com.fs.qw.domain.CustomerTransferApproval;
 import com.fs.qw.dto.FsUserTransferParamDTO;
 import com.fs.qw.service.ICustomerTransferApprovalService;
@@ -28,6 +30,8 @@ import org.springframework.web.bind.annotation.*;
 
 import java.util.Date;
 
+import static com.fs.his.utils.PhoneUtil.encryptPhone;
+
 @Api(tags = "会员管理接口")
 @RestController
 @Slf4j
@@ -60,6 +64,9 @@ public class FsUserAdminController extends BaseController {
         }else {
             param.setCompanyId(loginUser.getCompany().getCompanyId());
         }
+        if(param.getPhone()!=null && !"".equals(param.getPhone())){
+            param.setPhone(PhoneUtil.encryptPhone(param.getPhone()));
+        }
 //        if(param.getCompanyUserId() == null) {
 //            throw new IllegalArgumentException("当前销售不存在!");
 //        }

+ 64 - 0
fs-service/src/main/java/com/fs/company/domain/CompanyRedPackage.java

@@ -0,0 +1,64 @@
+package com.fs.company.domain;
+
+import com.fs.common.annotation.Excel;
+import com.fs.common.core.domain.BaseEntity;
+
+import java.util.Date;
+
+public class CompanyRedPackage extends BaseEntity {
+
+    private Long companyId;
+
+    @Excel(name = "公司名称")
+    private String companyName;
+
+    @Excel(name = "销售名称")
+    private String nickName;
+
+    @Excel(name = "红包金额")
+    private Double totalAmount;
+
+    @Excel(name = "统计时间")
+    private String dateTime;
+
+
+    public Long getCompanyId() {
+        return companyId;
+    }
+
+    public void setCompanyId(Long companyId) {
+        this.companyId = companyId;
+    }
+
+    public String getCompanyName() {
+        return companyName;
+    }
+
+    public void setCompanyName(String companyName) {
+        this.companyName = companyName;
+    }
+
+    public String getNickName() {
+        return nickName;
+    }
+
+    public void setNickName(String nickName) {
+        this.nickName = nickName;
+    }
+
+    public Double getTotalAmount() {
+        return totalAmount;
+    }
+
+    public void setTotalAmount(Double totalAmount) {
+        this.totalAmount = totalAmount;
+    }
+
+    public String getDateTime() {
+        return dateTime;
+    }
+
+    public void setDateTime(String dateTime) {
+        this.dateTime = dateTime;
+    }
+}

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

@@ -0,0 +1,18 @@
+package com.fs.company.dto;
+
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+@Data
+public class CompBuySmsDTO implements Serializable {
+    /**
+     * 公司id
+     */
+    private String companyId;
+    /**
+     * 套餐id
+     */
+    private String packageId;
+}

+ 13 - 0
fs-service/src/main/java/com/fs/company/dto/CompanyIdAndUserDTO.java

@@ -0,0 +1,13 @@
+package com.fs.company.dto;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.io.Serializable;
+
+@EqualsAndHashCode
+@Data
+public class CompanyIdAndUserDTO implements Serializable {
+    private Long companyId;
+    private Long companyUserId;
+}

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

@@ -0,0 +1,15 @@
+package com.fs.company.dto;
+
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+@Data
+public class RechargeDTO {
+    /**
+     * 充值金额
+     */
+    private BigDecimal amount;
+    private Long companyId;
+    private Long userId;
+}

+ 3 - 0
fs-service/src/main/java/com/fs/company/mapper/CompanyMoneyLogsMapper.java

@@ -3,6 +3,7 @@ package com.fs.company.mapper;
 import java.math.BigDecimal;
 import java.util.List;
 import com.fs.company.domain.CompanyMoneyLogs;
+import com.fs.company.domain.CompanyRedPackage;
 import com.fs.company.param.CompanyMoneyLogsParam;
 import com.fs.company.param.CompanyStoreOrderMoneyLogsListParam;
 import com.fs.company.vo.*;
@@ -320,4 +321,6 @@ public interface CompanyMoneyLogsMapper
             "</if>" +
             "</script>"})
     Integer selectCompanyMoneyLogsExport1Counts(@Param("maps")FsCompanyMoneyLogsExportParam param);
+
+    List<CompanyRedPackage> selectCompanyRedPackageListVO(CompanyRedPackage companyRedPackage);
 }

+ 16 - 0
fs-service/src/main/java/com/fs/company/service/CompanyRechargeOrderService.java

@@ -0,0 +1,16 @@
+package com.fs.company.service;
+
+import com.fs.company.domain.CompanyRechargeOrder;
+
+import java.util.List;
+
+public interface CompanyRechargeOrderService {
+
+    List<CompanyRechargeOrder> queryOverdueOrder();
+
+    void autoClosedOrder();
+
+    CompanyRechargeOrder createOrder(CompanyRechargeOrder order) throws Exception;
+
+    CompanyRechargeOrder queryOrder(String orderNo);
+}

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

@@ -3,6 +3,7 @@ package com.fs.company.service;
 import java.math.BigDecimal;
 import java.util.List;
 import com.fs.company.domain.CompanyMoneyLogs;
+import com.fs.company.domain.CompanyRedPackage;
 import com.fs.company.param.CompanyMoneyLogsParam;
 import com.fs.company.param.CompanyStoreOrderMoneyLogsListParam;
 import com.fs.company.vo.*;
@@ -91,4 +92,6 @@ public interface ICompanyMoneyLogsService
     Integer selectCompanyMoneyLogsExport1Counts(FsCompanyMoneyLogsExportParam param);
 
     void exportData(FsCompanyMoneyLogsExportParam param);
+
+    List<CompanyRedPackage> selectCompanyRedPackageListVO(CompanyRedPackage companyRedPackage);
 }

+ 17 - 0
fs-service/src/main/java/com/fs/company/service/ICompanyRechargeService.java

@@ -5,6 +5,8 @@ import java.util.List;
 
 import com.fs.common.core.domain.R;
 import com.fs.company.domain.CompanyRecharge;
+import com.fs.company.domain.CompanyRechargeOrder;
+import com.fs.company.dto.RechargeDTO;
 import com.fs.company.vo.CompanyRechargeExportVO;
 import com.fs.company.vo.CompanyRechargeVO;
 
@@ -72,6 +74,7 @@ public interface ICompanyRechargeService
     CompanyRecharge selectCompanyRechargeByNo(String s);
 
     R payNotify(CompanyRecharge recharge);
+    R payNotify(String orderNo,String transactionId);
 
     BigDecimal selectCompanyRechargeMoney();
 
@@ -82,4 +85,18 @@ public interface ICompanyRechargeService
      * @return 充值集合
      */
     List<CompanyRechargeExportVO> selectCompanyRechargeExportList(CompanyRecharge companyRecharge);
+
+    /**
+     * 充值
+     * @param dto 参数
+     * @return 地址
+     */
+    CompanyRechargeOrder recharge(RechargeDTO dto) throws Exception;
+
+    /**
+     * 查询订单
+     * @param orderNo 订单号
+     * @return CompanyRechargeOrder
+     */
+    CompanyRechargeOrder queryOrder(String orderNo);
 }

+ 6 - 0
fs-service/src/main/java/com/fs/company/service/impl/CompanyMoneyLogsServiceImpl.java

@@ -13,6 +13,7 @@ import com.fs.common.utils.SecurityUtils;
 import com.fs.common.utils.StringUtils;
 import com.fs.common.utils.poi.ExcelUtil;
 import com.fs.company.domain.CompanyDept;
+import com.fs.company.domain.CompanyRedPackage;
 import com.fs.company.domain.CompanyUser;
 import com.fs.company.param.CompanyMoneyLogsParam;
 import com.fs.company.param.CompanyStoreOrderMoneyLogsListParam;
@@ -246,4 +247,9 @@ public class CompanyMoneyLogsServiceImpl implements ICompanyMoneyLogsService
             fsExportTaskMapper.updateFsExportTask(task);
         }
     }
+
+    @Override
+    public List<CompanyRedPackage> selectCompanyRedPackageListVO(CompanyRedPackage companyRedPackage) {
+        return companyMoneyLogsMapper.selectCompanyRedPackageListVO(companyRedPackage);
+    }
 }

+ 4 - 1
fs-service/src/main/java/com/fs/company/service/impl/CompanyRechargeOrderServiceImpl.java

@@ -7,7 +7,9 @@ import com.fs.company.domain.CompanyRechargeOrder;
 import com.fs.company.mapper.CompanyRechargeOrderMapper;
 import com.fs.company.service.ICompanyRechargeOrderService;
 import com.fs.company.util.OrderUtils;
+import com.fs.company.service.CompanyRechargeOrderService;
 import com.fs.core.config.WxPayProperties;
+import com.fs.wx.utils.OrderUtils;
 import com.github.binarywang.wxpay.bean.order.WxPayNativeOrderResult;
 import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
 import com.github.binarywang.wxpay.config.WxPayConfig;
@@ -23,7 +25,8 @@ import java.time.LocalDateTime;
 import java.util.List;
 
 @Service
-public class CompanyRechargeOrderServiceImpl implements ICompanyRechargeOrderService {
+//public class CompanyRechargeOrderServiceImpl implements ICompanyRechargeOrderService {
+public class CompanyRechargeOrderServiceImpl implements CompanyRechargeOrderService {
     @Autowired
     private CompanyRechargeOrderMapper companyRechargeOrderMapper;
 

+ 61 - 3
fs-service/src/main/java/com/fs/company/service/impl/CompanyRechargeServiceImpl.java

@@ -4,19 +4,27 @@ import java.math.BigDecimal;
 import java.util.Date;
 import java.util.List;
 
+import cn.hutool.core.util.ObjectUtil;
 import com.fs.common.core.domain.R;
 import com.fs.common.utils.DateUtils;
+import com.fs.company.constant.PaymentStatus;
 import com.fs.company.domain.Company;
 import com.fs.company.domain.CompanyMoneyLogs;
+import com.fs.company.domain.CompanyRechargeOrder;
+import com.fs.company.dto.RechargeDTO;
 import com.fs.company.mapper.CompanyMapper;
 import com.fs.company.mapper.CompanyMoneyLogsMapper;
+import com.fs.company.mapper.CompanyRechargeOrderMapper;
+import com.fs.company.service.CompanyRechargeOrderService;
 import com.fs.company.vo.CompanyRechargeExportVO;
 import com.fs.company.vo.CompanyRechargeVO;
+import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import com.fs.company.mapper.CompanyRechargeMapper;
 import com.fs.company.domain.CompanyRecharge;
 import com.fs.company.service.ICompanyRechargeService;
+import org.springframework.transaction.annotation.Propagation;
 import org.springframework.transaction.annotation.Transactional;
 
 /**
@@ -25,6 +33,7 @@ import org.springframework.transaction.annotation.Transactional;
  * @author fs
  * @date 2021-10-04
  */
+@Slf4j
 @Service
 public class CompanyRechargeServiceImpl implements ICompanyRechargeService
 {
@@ -34,6 +43,8 @@ public class CompanyRechargeServiceImpl implements ICompanyRechargeService
     private CompanyMoneyLogsMapper moneyLogsMapper;
     @Autowired
     private CompanyMapper companyMapper;
+    @Autowired
+    private CompanyRechargeOrderService companyRechargeOrderService;
     /**
      * 查询充值
      *
@@ -120,13 +131,13 @@ public class CompanyRechargeServiceImpl implements ICompanyRechargeService
     }
 
     @Override
-    @Transactional
+    @Transactional(rollbackFor = Throwable.class,propagation = Propagation.REQUIRED)
     public R payNotify(CompanyRecharge recharge) {
         //修改状态
         recharge.setPayTime(new Date());
         recharge.setStatus(1);
         companyRechargeMapper.updateCompanyRecharge(recharge);
-        Company company=companyMapper.selectCompanyById(recharge.getCompanyId());
+        Company company=companyMapper.selectCompanyByIdForUpdate(recharge.getCompanyId());
         company.setMoney(company.getMoney().add(recharge.getMoney()));
         //写入日志
         CompanyMoneyLogs log=new CompanyMoneyLogs();
@@ -134,7 +145,7 @@ public class CompanyRechargeServiceImpl implements ICompanyRechargeService
         log.setMoney(recharge.getMoney());
         log.setRemark("充值金额:"+recharge.getMoney()+"元");
         log.setCreateTime(new Date());
-        log.setLogsType(1);
+        log.setLogsType(3);
         log.setBalance(company.getMoney());
         moneyLogsMapper.insertCompanyMoneyLogs(log);
         //修改余额
@@ -144,6 +155,38 @@ public class CompanyRechargeServiceImpl implements ICompanyRechargeService
         return R.ok();
     }
 
+    @Autowired
+    private CompanyRechargeOrderMapper companyRechargeOrderMapper;
+
+    @Override
+    public synchronized R payNotify(String orderNo,String transactionId) {
+        CompanyRechargeOrder order = companyRechargeOrderMapper.selectByOrderNo(orderNo);
+
+        if(ObjectUtil.equal(order.getPayStatus(), PaymentStatus.SUCCESS.getCode())){
+            log.info("订单已支付!重复付款 {} {}", orderNo,transactionId);
+            R.ok();
+        }
+        //修改状态
+        order.setPayStatus(PaymentStatus.SUCCESS.getCode());
+        order.setTransactionId(transactionId);
+        companyRechargeOrderMapper.updateByOrderNo(order);
+
+        Company company=companyMapper.selectCompanyByIdForUpdate(order.getCompanyId());
+        //写入日志
+        CompanyMoneyLogs log=new CompanyMoneyLogs();
+        log.setCompanyId(order.getCompanyId());
+        log.setMoney(order.getPayAmount());
+        log.setRemark("充值金额:"+order.getPayAmount()+"元");
+        log.setCreateTime(new Date());
+        log.setLogsType(3);
+        log.setBalance(company.getMoney());
+        moneyLogsMapper.insertCompanyMoneyLogs(log);
+        //修改余额
+        company.setMoney(company.getMoney().add(order.getPayAmount()));
+        companyMapper.updateCompany(company);
+        return R.ok();
+    }
+
     @Override
     public BigDecimal selectCompanyRechargeMoney() {
         return companyRechargeMapper.selectCompanyRechargeMoney();
@@ -153,4 +196,19 @@ public class CompanyRechargeServiceImpl implements ICompanyRechargeService
     public List<CompanyRechargeExportVO> selectCompanyRechargeExportList(CompanyRecharge companyRecharge) {
         return companyRechargeMapper.selectCompanyRechargeExportList(companyRecharge);
     }
+
+    @Override
+    @Transactional(propagation = Propagation.REQUIRED,rollbackFor = Throwable.class)
+    public CompanyRechargeOrder recharge(RechargeDTO dto) throws Exception {
+        CompanyRechargeOrder order = new CompanyRechargeOrder();
+        order.setPayAmount(dto.getAmount());
+        order.setCompanyId(dto.getCompanyId());
+        order.setUserId(dto.getUserId());
+        return companyRechargeOrderService.createOrder(order);
+    }
+
+    @Override
+    public CompanyRechargeOrder queryOrder(String orderNo) {
+        return companyRechargeOrderService.queryOrder(orderNo);
+    }
 }

+ 2 - 2
fs-service/src/main/java/com/fs/core/config/WxOpenProperties.java

@@ -9,7 +9,7 @@ import org.springframework.context.annotation.Configuration;
 @ConfigurationProperties("wx.open")
 public class WxOpenProperties {
 
-    private String appId = "wx703c4bd07bbd1695";
+    private String appId = "wxcb1e78baf03c0662";
 
-    private String secret = "034f5cc8d9b5151f9d25da9628541e35";
+    private String secret = "d041d3e2392a68a3e86dc22d976ed4a0";
 }

+ 3 - 0
fs-service/src/main/java/com/fs/core/config/WxPayProperties.java

@@ -21,6 +21,8 @@ public class WxPayProperties {
    */
   private String mchKey;
 
+  private String v3Key;
+
   /**
    * 服务商模式下的子商户公众账号ID,普通模式请不要配置,请在配置文件中将对应项删除
    */
@@ -73,6 +75,7 @@ public class WxPayProperties {
   public String getSubAppId() {
     return subAppId;
   }
+  private String privateKeyPath;
 
   public void setSubAppId(String subAppId) {
     this.subAppId = subAppId;

+ 1 - 0
fs-service/src/main/java/com/fs/course/config/CourseConfig.java

@@ -39,6 +39,7 @@ public class CourseConfig implements Serializable {
     private String sidebarImageUrl;//侧边栏公共图
     private Integer delayStart;
     private Integer delayEnd;
+    private Integer isNegative;//是否为负数 0、不允许,1、允许
 
     /**
      * 小程序授权头像昵称方式(目前仅会员看课有效)

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

@@ -50,7 +50,7 @@ public class FsCourseRedPacketLog extends BaseEntity
     @Excel(name = "分享企微userid")
     private String qwUserId;
 
-    private Integer status;//状态 0 发送中  1  已发送
+    private Integer status;//状态 0 发送中  1  已发送 ,2、待发送
 
 
     private Long watchLogId;//观看记录 id

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

@@ -97,6 +97,4 @@ public class FsVideoResource {
     private String transcodeFileKey;//转码的文件key
 
     private Integer sort;
-
-    private Long userId;
 }

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

@@ -424,4 +424,9 @@ public interface FsCourseWatchLogMapper extends BaseMapper<FsCourseWatchLog> {
     List<QwExternalContact> selectQwWatchLogFomExtContact(@Param("logIds") List<Long> logIds);
 
     List<FsCourseWatchLogListVO> selectListBytrainingCampId(PeriodStatisticCountParam param);
+    @Select("select * from fs_course_watch_log " +
+            "where " +
+            "video_id = #{videoId} " +
+            "and user_id = #{userId} limit 1 ")
+    FsCourseWatchLog getWatchCourseVideoByUserId(@Param("userId") Long userId,@Param("videoId") Long videoId);
 }

+ 5 - 7
fs-service/src/main/java/com/fs/course/mapper/FsUserCourseMapper.java

@@ -140,9 +140,6 @@ public interface FsUserCourseMapper
             "<if test = ' maps.subCateId !=null '> " +
             "and c.sub_cate_id =#{maps.subCateId}" +
             "</if>" +
-            "<if test = ' maps.userId !=null '> " +
-            "and c.user_id =#{maps.userId}" +
-            "</if>" +
             "<if test = ' maps.courseName!=null and maps.courseName != \"\" '> " +
             "and c.course_name like concat('%', #{maps.courseName}, '%') " +
             "</if>" +
@@ -231,8 +228,8 @@ public interface FsUserCourseMapper
     List<FsUserCourseListPVO> selectFsUserCourseListCompanyPVO(@Param("maps")FsUserCourseParam fsUserCourse);
 
 
-
-    List<OptionsVO> selectFsUserCourseAllList(@Param("userId") Long userId);
+    @Select("select course_id dict_value, course_name dict_label,img_url dict_imgUrl  from fs_user_course where is_del = 0 and is_private = 1 ")
+    List<OptionsVO> selectFsUserCourseAllList();
 
     @Select("select course_id dict_value, course_name dict_label,img_url dict_imgUrl  from fs_user_course where is_del = 0 and is_private = 1" +
             " and find_in_set(#{companyId},company_ids) ")
@@ -281,12 +278,13 @@ public interface FsUserCourseMapper
      */
     Integer selectTodayCourseWatchLogCountByUserIdAndProjectId(@Param("userId") Long userId, @Param("projectId") Long projectId);
 
-    @Select("select course_id,course_name,description,img_url,second_img secondImg,views from fs_user_course where is_private = 0 order by sort,course_id")
+    @Select("select course_id,course_name,description,img_url,second_img secondImg,views from fs_user_course where " +
+            " is_private = 0 and is_del = 0 order by sort,course_id")
     List<FsUserCourseVideoAppletVO> selectFsUserCourseVideoApplet();
 
     @Select("select video_id,title,course_id,video_url,SEC_TO_TIME(duration) as total_duration," +
             "thumbnail videoImgUrl,description videoDescription,video_url videoUrl,question_bank_id questionBankId " +
-            " from fs_user_course_video where course_id = #{courseId}  order by course_sort,video_id")
+            " from fs_user_course_video where course_id = #{courseId} and is_del = 0 order by course_sort,video_id")
     List<FsUserCourseVideoAppletVO.FsUserCourseVideo> selectFsUserCourseVideoAppletByCourseId(@Param("courseId") Long courseId);
 
 }

+ 0 - 3
fs-service/src/main/java/com/fs/course/mapper/FsUserCourseVideoMapper.java

@@ -85,9 +85,6 @@ public interface FsUserCourseVideoMapper
             "<if test = ' maps.title!=null and maps.title != \"\" '> " +
             "and v.title = #{maps.title} " +
             "</if>" +
-            "<if test = ' maps.userId!=null and maps.userId != \"\" '> " +
-            "and v.user_id = #{maps.userId} " +
-            "</if>" +
             " order by v.course_sort  "+
             "</script>"})
     List<FsUserCourseVideo> selectFsUserCourseVideoListByCourseId(@Param("maps") FsUserCourseVideo fsUserCourseVideo);

+ 2 - 0
fs-service/src/main/java/com/fs/course/param/FsUserCourseVideoAddKfUParam.java

@@ -64,4 +64,6 @@ public class FsUserCourseVideoAddKfUParam implements Serializable {
     private String chatId;
     private String nickName;
 
+    private Integer isOpenCourse;
+
 }

+ 1 - 1
fs-service/src/main/java/com/fs/course/param/newfs/FsUserCourseAddCompanyUserParam.java

@@ -36,5 +36,5 @@ public class FsUserCourseAddCompanyUserParam implements Serializable {
 //    @NotNull(message = "项目id不能为空")
     @ApiModelProperty(value = "项目ID")
     private Long projectId;
-
+    private Integer isOpenCourse;
 }

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

@@ -73,7 +73,7 @@ public interface IFsCourseQuestionBankService
      * @param nickName 昵称
      * @return String
      */
-    String importData(List<FsCourseQuestionBankImportDTO> list, String nickName, Long userId);
+    String importData(List<FsCourseQuestionBankImportDTO> list, String nickName);
 
     /**
      * 根据ID查询题目

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

@@ -84,4 +84,5 @@ public interface IFsCourseRedPacketLogService
 
     R retryCourseRedPacketLog(Long[] logIds);
 
+    void sendRedPacketBf();
 }

+ 2 - 2
fs-service/src/main/java/com/fs/course/service/IFsUserCourseService.java

@@ -85,7 +85,7 @@ public interface IFsUserCourseService
 
     List<FsUserCourseListUVO> selectFsUserCourseListUVO(FsUserCourseListUParam param);
 
-    List<OptionsVO> selectFsUserCourseAllList(Long userId);
+    List<OptionsVO> selectFsUserCourseAllList();
 
     List<FsUserCourseListPVO> selectFsUserCourseListPVO(FsUserCourse param);
 
@@ -123,7 +123,7 @@ public interface IFsUserCourseService
 
     String createUserImageQR(@NotNull(message = "链接不能为空") String realLink, String backgroundImagePath, InputStream inputStream, String png, @NotNull(message = "销售id不能为空") Long companyUserId) throws Exception;
 
-    int copyFsUserCourse(Long courseId, Long userId);
+    int copyFsUserCourse(Long courseId);
 
     List<FsUserCourseVideoAppletVO> selectFsUserCourseVideoApplet();
 

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

@@ -30,7 +30,7 @@ public interface IFsUserCourseTrainingCampService extends IService<FsUserCourseT
      * 新增训练营
      * @param params    参数
      */
-    void add(FsUserCourseTrainingCampDTO params,Long userId);
+    void add(FsUserCourseTrainingCampDTO params);
     /**
      * 删除训练营
      * @param ids   ids

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

@@ -36,7 +36,6 @@ public interface IFsUserCourseVideoService
      * @return 课堂视频
      */
     public FsUserCourseVideo selectFsUserCourseVideoByVideoId(Long videoId);
-    public FsUserCourseVideoQVO selectFsUserCourseVideoByVideoIdVO(Long videoId,Long userId);
 
     /**
      * 查询课堂视频列表

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

@@ -362,7 +362,7 @@ public class FsCourseQuestionBankServiceImpl implements IFsCourseQuestionBankSer
      * @return String
      */
     @Override
-    public String importData(List<FsCourseQuestionBankImportDTO> list, String nickName,Long userId) {
+    public String importData(List<FsCourseQuestionBankImportDTO> list, String nickName) {
         if (Objects.isNull(list) || list.isEmpty()) {
             throw new ServiceException("导入数据不能为空");
         }
@@ -382,7 +382,6 @@ public class FsCourseQuestionBankServiceImpl implements IFsCourseQuestionBankSer
 
                 // 构建题目对象
                 FsCourseQuestionBank questionBank = buildQuestionBank(importDTO, categoryData, nickName);
-                questionBank.setUserId(userId);
                 importData.add(questionBank);
                 result.addSuccess(importDTO.getTitle());
 

+ 142 - 0
fs-service/src/main/java/com/fs/course/service/impl/FsCourseRedPacketLogServiceImpl.java

@@ -4,6 +4,7 @@ import java.math.BigDecimal;
 import java.util.Date;
 import java.util.List;
 
+import cn.hutool.json.JSONUtil;
 import com.alibaba.fastjson.JSON;
 import com.fs.common.core.domain.R;
 import com.fs.common.utils.DateUtils;
@@ -11,6 +12,7 @@ import com.fs.company.domain.Company;
 import com.fs.company.domain.CompanyMoneyLogs;
 import com.fs.company.mapper.CompanyMapper;
 import com.fs.company.mapper.CompanyMoneyLogsMapper;
+import com.fs.course.config.CourseConfig;
 import com.fs.course.domain.FsCourseWatchLog;
 import com.fs.course.mapper.FsCourseWatchLogMapper;
 import com.fs.course.param.FsCourseRedPacketLogParam;
@@ -19,7 +21,10 @@ import com.fs.his.domain.FsUser;
 import com.fs.his.mapper.FsUserMapper;
 import com.fs.his.param.WxSendRedPacketParam;
 import com.fs.his.service.IFsStorePaymentService;
+import com.fs.system.service.ISysConfigService;
 import com.github.binarywang.wxpay.bean.transfer.TransferBillsResult;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import com.fs.course.mapper.FsCourseRedPacketLogMapper;
@@ -36,10 +41,14 @@ import org.springframework.transaction.annotation.Transactional;
 @Service
 public class FsCourseRedPacketLogServiceImpl implements IFsCourseRedPacketLogService
 {
+    private static final Logger logger = LoggerFactory.getLogger(FsCourseRedPacketLogServiceImpl.class);
     @Autowired
     private FsCourseRedPacketLogMapper fsCourseRedPacketLogMapper;
     @Autowired
     private CompanyMapper companyMapper;
+
+    @Autowired
+    private ISysConfigService configService;
     /**
      * 查询短链课程看课记录
      *
@@ -248,4 +257,137 @@ public class FsCourseRedPacketLogServiceImpl implements IFsCourseRedPacketLogSer
         return R.ok("成功:"+suc+" 失败:"+err);
     }
 
+    @Override
+    public void sendRedPacketBf() {
+        try {
+            logger.info("【红包发放】开始执行红包发放任务");
+
+            // 初始化查询对象
+            FsCourseRedPacketLog query = new FsCourseRedPacketLog();
+            query.setStatus(2); // 状态2表示待处理红包
+
+            // 获取红包配置
+            String json = configService.selectConfigByKey("course.config");
+            CourseConfig config = JSONUtil.toBean(json, CourseConfig.class);
+            logger.info("【红包发放】当前红包发放模式:{}", config.getRedPacketMode());
+
+            // 获取待处理红包列表
+            List<FsCourseRedPacketLog> pendingPackets = fsCourseRedPacketLogMapper.selectFsCourseRedPacketLogList(query);
+            if (pendingPackets == null || pendingPackets.isEmpty()) {
+                logger.info("【红包发放】没有待处理的红包记录");
+                return;
+            }
+
+            logger.info("【红包发放】共发现{}条待处理红包记录", pendingPackets.size());
+
+            // 处理每条红包记录
+            for (FsCourseRedPacketLog redPacket : pendingPackets) {
+                try {
+                    logger.info("【红包处理】开始处理红包记录ID:{},用户ID:{},金额:{}元",
+                            redPacket.getLogId(), redPacket.getUserId(), redPacket.getAmount());
+
+                    processRedPacket(redPacket, config);
+                } catch (Exception e) {
+                    logger.error("【红包处理】处理红包记录ID:{}时发生异常", redPacket.getLogId(), e);
+                    // 即使一条记录失败也继续处理下一条
+                }
+            }
+
+            logger.info("【红包发放】红包发放任务执行完成");
+        } catch (Exception e) {
+            logger.error("【红包发放】红包发放任务执行过程中发生未预期异常", e);
+        }
+    }
+
+    private void processRedPacket(FsCourseRedPacketLog redPacket, CourseConfig config) {
+        // 获取用户信息
+        FsUser user = fsUserMapper.selectFsUserByUserId(redPacket.getUserId());
+        if (user == null || user.getMpOpenId() == null) {
+            logger.error("【红包处理】错误:未找到用户ID:{}或用户缺少openId", redPacket.getUserId());
+            return;
+        }
+
+        logger.info("【红包处理】准备为用户{}发放红包,openId:{}", user.getUserId(), user.getMpOpenId());
+
+        // 准备红包参数
+        WxSendRedPacketParam packetParam = new WxSendRedPacketParam();
+        packetParam.setOpenId(user.getMpOpenId());
+        packetParam.setAmount(redPacket.getAmount());
+        packetParam.setSource(2);
+        packetParam.setAppId(redPacket.getAppId());
+        packetParam.setRedPacketMode(config.getRedPacketMode());
+        packetParam.setCompanyId(redPacket.getCompanyId());
+
+        // 处理企业资金(使用悲观锁)
+        Company company = companyMapper.selectCompanyByIdForUpdate(redPacket.getCompanyId());
+        if (company == null) {
+            logger.error("【红包处理】错误:未找到企业ID:{}", redPacket.getCompanyId());
+            return;
+        }
+
+        BigDecimal remainingBalance = company.getMoney().subtract(redPacket.getAmount());
+        if (remainingBalance.compareTo(BigDecimal.ZERO) < 0) {
+            logger.warn("【红包处理】企业{}余额不足(当前余额:{}元,需要扣除:{}元)",
+                    company.getCompanyId(), company.getMoney(), redPacket.getAmount());
+            return;
+        }
+
+        logger.info("【红包处理】企业{}当前余额:{}元,发放后余额:{}元",
+                company.getCompanyId(), company.getMoney(), remainingBalance);
+
+        // 发送红包
+        R sendRedPacketResult = paymentService.sendRedPacket(packetParam);
+        if (sendRedPacketResult == null) {
+            logger.error("【红包处理】红包接口返回空结果");
+            return;
+        }
+
+        if (!sendRedPacketResult.get("code").equals(200)) {
+            logger.error("【红包处理】红包发放失败,错误码:{},错误信息:{}",
+                    sendRedPacketResult.get("code"), sendRedPacketResult.get("msg"));
+            return;
+        }
+
+        // 处理成功结果
+        logger.info("【红包处理】红包发放成功");
+
+        // 更新红包记录
+        if (sendRedPacketResult.get("isNew").equals(1)) {
+            TransferBillsResult transferBillsResult = (TransferBillsResult)sendRedPacketResult.get("data");
+            redPacket.setResult(JSON.toJSONString(sendRedPacketResult));
+            redPacket.setOutBatchNo(transferBillsResult.getOutBillNo());
+            logger.info("【红包处理】新批次红包,批次号:{}", transferBillsResult.getOutBillNo());
+        } else {
+            redPacket.setOutBatchNo(sendRedPacketResult.get("orderCode").toString());
+            logger.info("【红包处理】已有批次红包,订单号:{}", redPacket.getOutBatchNo());
+        }
+
+        fsCourseRedPacketLogMapper.updateFsCourseRedPacketLog(redPacket);
+
+        // 更新观看记录
+        FsCourseWatchLog watchLog = courseWatchLogMapper.selectFsCourseWatchLogByLogId(redPacket.getLogId());
+        if (watchLog != null) {
+            watchLog.setRewardType(config.getRewardType());
+            courseWatchLogMapper.updateFsCourseWatchLog(watchLog);
+            logger.info("【红包处理】更新观看记录{}的奖励类型为{}", watchLog.getLogId(), config.getRewardType());
+        }
+
+        // 更新企业余额
+        company.setMoney(remainingBalance);
+        companyMapper.updateCompany(company);
+
+        // 记录资金流水
+        CompanyMoneyLogs moneyLog = new CompanyMoneyLogs();
+        moneyLog.setCompanyId(company.getCompanyId());
+        moneyLog.setRemark("扣除红包金额");
+        moneyLog.setMoney(redPacket.getAmount().multiply(new BigDecimal(-1)));
+        moneyLog.setLogsType(15);
+        moneyLog.setBalance(company.getMoney());
+        moneyLog.setCreateTime(new Date());
+        moneyLogsMapper.insertCompanyMoneyLogs(moneyLog);
+
+        logger.info("【红包处理】企业资金流水记录成功,企业ID:{},变动金额:{}元",
+                company.getCompanyId(), moneyLog.getMoney());
+    }
+
 }

+ 5 - 6
fs-service/src/main/java/com/fs/course/service/impl/FsUserCourseServiceImpl.java

@@ -277,18 +277,19 @@ public class FsUserCourseServiceImpl implements IFsUserCourseService
     }
 
     @Override
-    public List<OptionsVO> selectFsUserCourseAllList(Long userId) {
-        return fsUserCourseMapper.selectFsUserCourseAllList(userId);
+    public List<OptionsVO> selectFsUserCourseAllList() {
+        return fsUserCourseMapper.selectFsUserCourseAllList();
     }
 
 
     @Override
     public List<FsUserCourseListPVO> selectFsUserCourseListPVO(FsUserCourse param) {
+
+        List<FsUserCourseListPVO> list =  fsUserCourseMapper.selectFsUserCourseListPVO(param);
         List<DictVO> dictVOS = sysDictDataMapper.selectDictDataListByType("sys_course_project");
         // Create a map for faster lookup (dictValue -> dictVO)
         Map<String, String> projectMap = dictVOS.stream()
                 .collect(Collectors.toMap(DictVO::getDictValue, DictVO::getDictLabel));
-        List<FsUserCourseListPVO> list =  fsUserCourseMapper.selectFsUserCourseListPVO(param);
         for (FsUserCourseListPVO vo : list) {
             if (vo.getProject() != null) {
                 String projectName = projectMap.get(vo.getProject().toString());
@@ -663,11 +664,10 @@ public class FsUserCourseServiceImpl implements IFsUserCourseService
 
     @Override
     @Transactional(rollbackFor = Exception.class) // 显式声明事务
-    public int copyFsUserCourse(Long courseId, Long userId) {
+    public int copyFsUserCourse(Long courseId) {
         FsUserCourse fsUserCourse = fsUserCourseService.selectFsUserCourseByCourseId(courseId);
         if(fsUserCourse != null){
             fsUserCourse.setCourseId(null);
-            fsUserCourse.setUserId(userId);
             fsUserCourseService.insertFsUserCourse(fsUserCourse);
             Long newCourseId = fsUserCourse.getCourseId();
 
@@ -677,7 +677,6 @@ public class FsUserCourseServiceImpl implements IFsUserCourseService
 
             FsUserCourseVideo fsUserCourseVideo = new FsUserCourseVideo();
             fsUserCourseVideo.setCourseId(courseId);
-            fsUserCourseVideo.setUserId(userId);
             List<FsUserCourseVideo> list = fsUserCourseVideoService.selectFsUserCourseVideoListByCourseId(fsUserCourseVideo);
             for (FsUserCourseVideo courseVideo : list) {
                 courseVideo.setVideoId(null);

+ 1 - 2
fs-service/src/main/java/com/fs/course/service/impl/FsUserCourseTrainingCampServiceImpl.java

@@ -62,12 +62,11 @@ public class FsUserCourseTrainingCampServiceImpl extends ServiceImpl<FsUserCours
      * @param params    参数
      */
     @Override
-    public void add(FsUserCourseTrainingCampDTO params,Long userId) {
+    public void add(FsUserCourseTrainingCampDTO params) {
         FsUserCourseTrainingCamp trainingCamp = new FsUserCourseTrainingCamp();
         trainingCamp.setTrainingCampName(params.getTrainingCampName());
         trainingCamp.setOrderNumber(baseMapper.getOrderNumber());
         trainingCamp.setCreateTime(LocalDateTime.now());
-        trainingCamp.setUserId(userId);
         baseMapper.insert(trainingCamp);
     }
 

+ 174 - 40
fs-service/src/main/java/com/fs/course/service/impl/FsUserCourseVideoServiceImpl.java

@@ -4,6 +4,7 @@ import cn.hutool.json.JSONUtil;
 import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.Wrapper;
+import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.fs.common.BeanCopyUtils;
 import com.fs.common.core.domain.R;
@@ -214,28 +215,6 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
         return fsUserCourseVideoMapper.selectFsUserCourseVideoByVideoId(videoId);
     }
 
-    @Override
-    public FsUserCourseVideoQVO selectFsUserCourseVideoByVideoIdVO(Long videoId,Long userId) {
-        FsUserCourseVideoQVO fsUserCourseVideoQVO=new FsUserCourseVideoQVO();
-        FsUserCourseVideo courseVideo = fsUserCourseVideoMapper.selectFsUserCourseVideoByVideoIdAndUserId(videoId,userId);
-
-        BeanCopyUtils.copy(courseVideo,fsUserCourseVideoQVO);
-        if (courseVideo.getRedPacketMoney()!=null){
-            fsUserCourseVideoQVO.setRedPacketMoney(courseVideo.getRedPacketMoney().toString());
-        }
-        if (StringUtils.isNotEmpty(courseVideo.getQuestionBankId())){
-            List<FsCourseQuestionBank> fsCourseQuestionBanks = courseQuestionBankMapper.selectFsCourseQuestionBankByIdVO(courseVideo.getQuestionBankId().split(","));
-            fsUserCourseVideoQVO.setQuestionBankList(fsCourseQuestionBanks);
-        }
-        //返回课程关联的拍商品
-        if(courseVideo.getIsProduct() != null && courseVideo.getIsProduct() == 1 && courseVideo.getProductId() != null){
-            FsCourseProduct courseProduct = courseProductMapper.selectFsCourseProductById(courseVideo.getProductId());
-            List<FsCourseProduct> courseProducts = Arrays.asList(courseProduct);
-            fsUserCourseVideoQVO.setCourseProducts(courseProducts);
-        }
-        return fsUserCourseVideoQVO;
-    }
-
     /**
      * 查询课堂视频列表
      *
@@ -428,7 +407,21 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
         if (fsUser.getStatus()==0){
             return R.error("会员被停用,无权限,请联系客服!");
         }
-
+//        if (param.getIsOpenCourse()!=null&&param.getIsOpenCourse()==1){
+//            FsCourseWatchLog log = courseWatchLogMapper.getWatchCourseVideoByUserId(param.getUserId(), param.getVideoId());
+//            if (log==null){
+//                FsCourseWatchLog userLog = new FsCourseWatchLog();
+//                BeanUtils.copyProperties(param,log);
+//                userLog.setSendType(0);
+//                userLog.setUserId(param.getUserId());
+//                userLog.setVideoId(param.getVideoId());
+//                userLog.setDuration(0L);
+//                userLog.setCreateTime(new Date());
+//                userLog.setLogType(3);
+//                courseWatchLogMapper.insertFsCourseWatchLog(log);
+//            }
+//            return  R.ok();
+//        }
         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>";
 //        try {
@@ -888,14 +881,14 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
         if (log.getRewardType() != null) {
             FsCourseRedPacketLog packetLog = redPacketLogMapper.selectFsCourseRedPacketLogByTemporary(param.getVideoId(), param.getUserId());
             if(packetLog != null && packetLog.getStatus() == 1) {
-                return R.error("奖励已发放");
+                return R.error("已领取该课程奖励,不可重复领取!");
             }
             if(packetLog != null && packetLog.getStatus() == 0) {
                 if(StringUtils.isNotEmpty(packetLog.getResult())){
                     R r = JSON.parseObject(packetLog.getResult(), R.class);
                     return r;
                 } else {
-                    return R.error("奖励已发放");
+                    return R.error("操作频繁,请稍后再试!");
                 }
             }
             if(packetLog != null && packetLog.getStatus() == 2) {
@@ -936,14 +929,14 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
         if (log.getRewardType() != null) {
             FsCourseRedPacketLog fsCourseRedPacketLog = redPacketLogMapper.selectUserFsCourseRedPacketLog(param.getVideoId(), param.getUserId(),param.getPeriodId());
             if(fsCourseRedPacketLog != null && fsCourseRedPacketLog.getStatus() == 1) {
-                return R.error("奖励已发放");
+                return R.error("已领取该课程奖励,不可重复领取!");
             }
             if(fsCourseRedPacketLog != null && fsCourseRedPacketLog.getStatus() == 0) {
                 if(StringUtils.isNotEmpty(fsCourseRedPacketLog.getResult())){
                     R r = JSON.parseObject(fsCourseRedPacketLog.getResult(), R.class);
                     return r;
                 } else {
-                    return R.error();
+                    return R.error("操作频繁,请稍后再试!");
                 }
             }
         }
@@ -998,8 +991,12 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
         if (param.getSource() == 2) {
             //处理多小程序问题
             FsUserWx fsUserWx = fsUserWxService.selectByAppIdAndUserId(param.getAppId(),user.getUserId(),1);
-            if (fsUserWx ==null || fsUserWx.getOpenId()==null){
-                packetParam.setOpenId(user.getCourseMaOpenId());
+            if (fsUserWx ==null){
+                try {
+                    handleFsUserWx(user,param.getAppId());
+                }catch (Exception e){
+                    logger.error("zyp \n 【更新或插入用户与小程序的绑定关系失败】:{}", user.getUserId());
+                }
             }else {
                 packetParam.setOpenId(fsUserWx.getOpenId());
             }
@@ -1108,6 +1105,31 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
 
     }
 
+
+    private void handleFsUserWx(FsUser user, String appId) {
+        // 尝试更新
+        boolean updated = fsUserWxService.lambdaUpdate()
+                .eq(FsUserWx::getFsUserId, user.getUserId())
+                .eq(FsUserWx::getAppId,appId )
+                .eq(FsUserWx::getOpenId, user.getMaOpenId())
+//                .set(FsUserWx::getUnionId, session.getUnionid() == null ? "" : session.getUnionid())
+                .set(FsUserWx::getUpdateTime, new Date())
+                .update();
+
+        // 如果更新失败(记录不存在),则插入
+        if (!updated) {
+            FsUserWx fsUserWx = new FsUserWx();
+            fsUserWx.setType(1);
+            fsUserWx.setFsUserId(user.getUserId());
+            fsUserWx.setAppId(appId);
+            fsUserWx.setOpenId(user.getMaOpenId());
+//            fsUserWx.setUnionId(session.getUnionid() == null ? "" : session.getUnionid());
+            fsUserWx.setCreateTime(new Date());
+            fsUserWx.setUpdateTime(new Date());
+            fsUserWxService.save(fsUserWx);
+        }
+    }
+
     /**
      * 发放红包奖励
      *
@@ -1151,18 +1173,26 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
         // 来源是小程序切换openId
         if (param.getSource() == 2) {
             //处理多小程序问题
-            Company company = companyMapper.selectCompanyById(param.getCompanyId());
-            if (company.getCourseMiniAppId()==null){
-                return R.error("销售公司参数错误,未绑定小程序");
-            }
-            FsUserWx fsUserWx = fsUserWxService.selectByAppIdAndUserId(company.getCourseMiniAppId(),user.getUserId(),1);
+//            Company company = companyMapper.selectCompanyById(param.getCompanyId());
+//            if (company.getCourseMiniAppId()==null){
+//                return R.error("销售公司参数错误,未绑定小程序");
+//            }
+            FsUserWx fsUserWx = fsUserWxService.selectByAppIdAndUserId(param.getAppId(),user.getUserId(),1);
             if (fsUserWx ==null || fsUserWx.getOpenId()==null){
-                return R.error("小程序openId参数缺失");
+                packetParam.setOpenId(user.getCourseMaOpenId());
+                try {
+                    handleFsUserWx(user,param.getAppId());
+                }catch (Exception e){
+                    logger.error("zyp \n 【更新或插入用户与小程序的绑定关系失败】:{}", user.getUserId());
+                }
+
+            }else {
+                packetParam.setOpenId(fsUserWx.getOpenId());
             }
 
             System.out.println("小程序id"+user.getCourseMaOpenId());
             //查出公司绑定openid并赋值
-            packetParam.setOpenId(fsUserWx.getOpenId());
+//            packetParam.setOpenId(fsUserWx.getOpenId());
         }
         packetParam.setAmount(amount);
         packetParam.setSource(param.getSource());
@@ -1171,6 +1201,9 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
 
         System.out.println("红包金额"+amount);
         System.out.println("红包商户号"+packetParam);
+        if (ObjectUtils.isNotEmpty(config.getIsNegative())&&config.getIsNegative() == 1) {
+            return processRedPacket(config, packetParam, param, amount, log);
+        }
         //2025.6.19 红包金额为0的时候
         if (amount.compareTo(BigDecimal.ZERO)>0){
 
@@ -1183,13 +1216,14 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
                 redPacketLog.setCompanyId(param.getCompanyId());
                 redPacketLog.setUserId(param.getUserId());
                 redPacketLog.setVideoId(param.getVideoId());
-                redPacketLog.setStatus(2);
+                redPacketLog.setStatus(0);
                 redPacketLog.setQwUserId(param.getQwUserId() != null ? param.getQwUserId() : null);
                 redPacketLog.setCompanyUserId(param.getCompanyUserId());
                 redPacketLog.setCreateTime(new Date());
                 redPacketLog.setAmount(amount);
                 redPacketLog.setWatchLogId(log.getLogId() != null ? log.getLogId() : null);
                 redPacketLog.setPeriodId(param.getPeriodId());
+                redPacketLog.setAppId(param.getAppId());
                 redPacketLogMapper.insertFsCourseRedPacketLog(redPacketLog);
                 return R.error("销售公司余额不足");
             }
@@ -1218,6 +1252,7 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
                 redPacketLog.setAmount(amount);
                 redPacketLog.setWatchLogId(log.getLogId() != null ? log.getLogId() : null);
                 redPacketLog.setPeriodId(param.getPeriodId());
+                redPacketLog.setAppId(param.getAppId());
                 redPacketLogMapper.insertFsCourseRedPacketLog(redPacketLog);
 
                 // 更新观看记录的奖励类型
@@ -1254,6 +1289,7 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
             redPacketLog.setAmount(BigDecimal.ZERO);
             redPacketLog.setWatchLogId(log.getLogId() != null ? log.getLogId() : null);
             redPacketLog.setPeriodId(param.getPeriodId());
+            redPacketLog.setAppId(param.getAppId());
             redPacketLogMapper.insertFsCourseRedPacketLog(redPacketLog);
 
             // 更新观看记录的奖励类型
@@ -1266,6 +1302,64 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
 
     }
 
+    /**
+     * 直接发送奖励
+     *
+     * @param config
+     * @param packetParam
+     * @param param
+     * @param amount
+     * @param log
+     * @return
+     */
+    private R processRedPacket(CourseConfig config, WxSendRedPacketParam packetParam, FsCourseSendRewardUParam param, BigDecimal amount, FsCourseWatchLog log) {
+        R sendRedPacket = paymentService.sendRedPacket(packetParam);
+
+        if (!sendRedPacket.get("code").equals(200)) {
+            return R.error("奖励发送失败,请联系客服");
+        }
+
+        createRedPacketLog(sendRedPacket, param, amount, log);
+        updateWatchLogRewardType(log, config);
+
+        return sendRedPacket;
+    }
+
+    private void createRedPacketLog(R sendRedPacket, FsCourseSendRewardUParam param, BigDecimal amount, FsCourseWatchLog log) {
+        FsCourseRedPacketLog redPacketLog = new FsCourseRedPacketLog();
+
+        // Set common fields
+        redPacketLog.setCourseId(param.getCourseId());
+        redPacketLog.setCompanyId(param.getCompanyId());
+        redPacketLog.setUserId(param.getUserId());
+        redPacketLog.setVideoId(param.getVideoId());
+        redPacketLog.setStatus(0);
+        redPacketLog.setQwUserId(param.getQwUserId());
+        redPacketLog.setCompanyUserId(param.getCompanyUserId());
+        redPacketLog.setCreateTime(new Date());
+        redPacketLog.setAmount(amount);
+        redPacketLog.setWatchLogId(log != null ? log.getLogId() : null);
+        redPacketLog.setPeriodId(param.getPeriodId());
+        redPacketLog.setAppId(param.getAppId());
+
+        // Set batch number based on isNew flag
+        if (sendRedPacket.get("isNew").equals(1)) {
+            TransferBillsResult transferBillsResult = (TransferBillsResult) sendRedPacket.get("data");
+            redPacketLog.setResult(JSON.toJSONString(sendRedPacket));
+            redPacketLog.setOutBatchNo(transferBillsResult.getOutBillNo());
+        } else {
+            redPacketLog.setOutBatchNo(sendRedPacket.get("orderCode").toString());
+        }
+
+        redPacketLogMapper.insertFsCourseRedPacketLog(redPacketLog);
+    }
+
+    private void updateWatchLogRewardType(FsCourseWatchLog log, CourseConfig config) {
+        if (log != null) {
+            log.setRewardType(config.getRewardType());
+            courseWatchLogMapper.updateFsCourseWatchLog(log);
+        }
+    }
     /**
      * 获取用户openId
      *
@@ -1345,7 +1439,23 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
 
     @Override
     public List<FsUserCourseVideoPageListVO> pageListCourseVideo(UserCourseVideoPageParam param) {
-        return fsUserCourseVideoMapper.selectFsUserCourseVideoPageList(param);
+        List<FsUserCourseVideoPageListVO> courseVideoPageListVOList = fsUserCourseVideoMapper.selectFsUserCourseVideoPageList(param);
+        if (courseVideoPageListVOList.isEmpty()) {
+            return new LinkedList<>();
+        }
+
+        List<SysDictData> courseProject = dictDataMapper.selectDictDataByType("sys_course_project");
+        Map<String, String> projectMap = courseProject.stream()
+                .collect(Collectors.toMap(SysDictData::getDictValue, SysDictData::getDictLabel));
+
+        courseVideoPageListVOList.forEach(vo -> {
+            if (vo.getProjectId() != null) {
+                String projectName = projectMap.get(vo.getProjectId().toString());
+                vo.setProjectName(projectName);
+            }
+        });
+
+        return courseVideoPageListVOList;
     }
 
     @Override
@@ -1425,7 +1535,29 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
         if (fsUser == null){
             return ResponseResult.fail(404,"当前用户信息不存在");
         }
-
+        //公开课
+        if (param.getIsOpenCourse()!=null && param.getIsOpenCourse()==1){
+            FsCourseWatchLog watchCourseVideo = courseWatchLogMapper.getCourseWatchLogByUser(param.getUserId(), param.getVideoId());
+            //添加判断:该用户是否已经存在此课程的看课记录,并且看课记录的销售id不是传入的销售id
+            if(watchCourseVideo != null){
+                FsCourseWatchLog updateLog = new FsCourseWatchLog();
+                updateLog.setUpdateTime(new Date());
+                courseWatchLogMapper.updateFsCourseWatchLog(updateLog);
+            } else {
+                FsCourseWatchLog fsCourseWatchLog = new FsCourseWatchLog();
+                BeanUtils.copyProperties(param, fsCourseWatchLog);
+                fsCourseWatchLog.setSendType(1);
+                fsCourseWatchLog.setDuration(0L);
+                fsCourseWatchLog.setCreateTime(new Date());
+                fsCourseWatchLog.setLogType(1);
+                courseWatchLogMapper.insertFsCourseWatchLog(fsCourseWatchLog);
+                String redisKey = "h5wxuser:watch:heartbeat:" + param.getUserId() + ":" + param.getVideoId() + ":" + 0;
+                redisCache.setCacheObject(redisKey, LocalDateTime.now().toString());
+                // 设置 Redis 记录的过期时间(例如 5 分钟)
+                redisCache.expire(redisKey, 300, TimeUnit.SECONDS);
+            }
+            return ResponseResult.ok(Boolean.TRUE);
+        }
         //判断该销售是否存在
         CompanyUser companyUser = companyUserMapper.selectCompanyUserById(param.getCompanyUserId());
         if (companyUser == null){
@@ -1748,7 +1880,9 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
         if (param.getLinkType() != null && param.getLinkType() == 1){
             return R.ok();
         }
-
+        if (param.getCompanyUserId()==null){
+            param.setCompanyUserId(0L);
+        }
         // 从Redis中获取观看时长
         String redisKey = "h5wxuser:watch:duration:" + param.getUserId() + ":" + param.getVideoId() + ":" + param.getCompanyUserId();
         log.info("看课redis缓存key:{}", redisKey);

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

@@ -159,6 +159,7 @@ public class FsUser extends BaseEntity
         else{
             this.nickName= nickname;
         }
+        this.nickname = this.nickName;
     }
 
     public String getNickName()
@@ -183,4 +184,18 @@ public class FsUser extends BaseEntity
      * 项目ID
      */
     private Long projectId;
+
+    /**
+     * 昵称
+     * **/
+    @TableField(exist = false)
+    private String nickname;
+
+    public String getNickname() {
+        return nickname;
+    }
+
+    public void setNickname(String nickname) {
+        this.nickname = nickname;
+    }
 }

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

@@ -167,6 +167,10 @@ public class FsPackageServiceImpl implements IFsPackageService {
 
     @Override
     public List<FsPackageListVO> selectFsPackageListVO(FsPackageParam fsPackage) {
+        Integer privateType = fsPackage.getPrivateType();
+        if (privateType != null) {
+            fsPackage.setIsShow(0);
+        }
         return fsPackageMapper.selectFsPackageListVO(fsPackage);
     }
 

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

@@ -89,6 +89,7 @@ import com.fs.his.service.IFsUserService;
 import org.springframework.transaction.annotation.Propagation;
 import org.springframework.transaction.annotation.Transactional;
 
+import static com.fs.his.utils.PhoneUtil.decryptPhoneMk;
 import static com.fs.his.utils.PhoneUtil.encryptPhone;
 import static com.fs.hisStore.enums.BillDetailEnum.CATEGORY_1;
 import static com.fs.hisStore.enums.BillDetailEnum.CATEGORY_3;
@@ -577,6 +578,15 @@ public class FsUserServiceImpl implements IFsUserService
             if (StringUtils.isEmpty(fsUserPageListVO.getNickname())){
                 fsUserPageListVO.setNickname("用户暂未授权昵称");
             }
+
+            //解密
+            if(fsUserPageListVO.getPhone() != null && fsUserPageListVO.getPhone() != ""){
+                if (fsUserPageListVO.getPhone().length()>11){
+                    fsUserPageListVO.setPhone(decryptPhoneMk(fsUserPageListVO.getPhone()));
+                }else {
+                    fsUserPageListVO.setPhone(fsUserPageListVO.getPhone().replaceAll("(\\d{3})\\d*(\\d{4})", "$1****$2"));
+                }
+            }
         }
 
         return new PageInfo<>(fsUserPageListVOS);
@@ -706,6 +716,16 @@ public class FsUserServiceImpl implements IFsUserService
 //                    item.setIsRepeat(isRepeat);
 //                }
             }
+
+            // 解密
+            if(item.getPhone() != null && item.getPhone() != ""){
+                if (item.getPhone().length()>11){
+                    item.setPhone(decryptPhoneMk(item.getPhone()));
+                }else {
+                    item.setPhone(item.getPhone().replaceAll("(\\d{3})\\d*(\\d{4})", "$1****$2"));
+                }
+            }
+
         }
 
         TableDataInfo rspData = new TableDataInfo();

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

@@ -28,6 +28,8 @@ public class FsUserWxServiceImpl extends ServiceImpl<FsUserWxMapper, FsUserWx> i
                         .eq("app_id", appId)
                         .eq("fs_user_id", userId)
                         .eq("type", type)
+                        .orderByDesc("id")
+                        .last("LIMIT 1")
         );
     }
 }

+ 1 - 1
fs-service/src/main/java/com/fs/sop/mapper/QwSopTagMapper.java

@@ -63,7 +63,7 @@ public interface QwSopTagMapper extends BaseMapper<QwSopTag>{
      * @return 结果
      */
     int deleteQwSopTagByIds(Long[] ids);
-    @Select("select * from qw_sop_tag where status=1 and send_time > NOW() ")
+    @Select("select * from  qw_sop_tag where status=1 and send_time > NOW() ")
     List<QwSopTag> selectQwSopTagByStatus1();
 
 }

+ 12 - 0
fs-service/src/main/java/com/fs/statis/domain/FsStatisQwWatch.java

@@ -187,4 +187,16 @@ public class FsStatisQwWatch {
      */
     @Excel(name = "完课率")
     private BigDecimal finishedRate;
+
+    /**
+     * 流量数
+     */
+    @Excel(name = "流量数")
+    private Long trafficSum;
+
+    /**
+     * 注册数
+     */
+    @Excel(name = "注册数")
+    private Long regNum;
 }

+ 44 - 0
fs-service/src/main/java/com/fs/wx/utils/OrderUtils.java

@@ -0,0 +1,44 @@
+package com.fs.wx.utils;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+
+public class OrderUtils extends Thread {
+    private static long orderNum = 0L;
+    private static String date ;
+
+    public static void main(String[] args) throws InterruptedException {
+        for (int i = 0; i < 10000; i++) {
+            System.out.println(OrderUtils.getOrderNo());
+            Thread.sleep(1000);
+        }
+    }
+
+    /**
+     * 生成订单编号
+     * @return
+     */
+    public static synchronized String getOrderNo() {
+        String str = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());
+        if(date==null||!date.equals(str)){
+            date = str;
+            orderNum  = 0L;
+        }
+        orderNum ++;
+        long orderNo = Long.parseLong((date)) * 10000;
+        orderNo += orderNum;
+        return orderNo+"";
+    }
+
+    public static synchronized String genUserCode() {
+        String year = new SimpleDateFormat("yy").format(new Date());
+        String day = String.format("%tj", new Date());
+        double random = Math.random() * 1000;
+        int intRandom = Double.valueOf(random).intValue();
+        String verifyCode = year + day + intRandom;
+        return verifyCode;
+    }
+
+
+}

+ 4 - 3
fs-service/src/main/resources/application-config-druid-kyt.yml

@@ -60,8 +60,8 @@ watch:
   password3: v9xsKuqn_$d2y
 
 fs :
-  commonApi: http://172.16.0.16:8010
-  h5CommonApi: http://119.29.195.254:8010
+  commonApi: http://172.17.0.10:8010
+  h5CommonApi: http://172.17.0.10:8010
 nuonuo:
   key: 10924508
   secret: A2EB20764D304D16
@@ -79,7 +79,8 @@ cloud_host:
 headerImg:
   imgUrl: https://yztcourse-1325300895.cos.ap-guangzhou.myqcloud.com/yztcourse/20250523/e04871a98cc84be39a7f60c084698e21.jpg
 ipad:
-  ipadUrl: http://ipad.cdwjyyh.com
+  ipadUrl:
+  aiApi:
 wx_miniapp_temp:
   pay_order_temp_id:
   inquiry_temp_id:

+ 18 - 0
fs-service/src/main/resources/application-dev.yml

@@ -144,3 +144,21 @@ rocketmq:
         group: test-group
         access-key: ak1243b25nj17d4b2dc1a03 # 替换为实际的 accessKey
         secret-key: sk08a7ea1f9f4b0237 # 替换为实际的 secretKey
+custom:
+    token: "1o62d3YxvdHd4LEUiltnu7sK"
+    encoding-aes-key: "UJfTQ5qKTKlegjkXtp1YuzJzxeHlUKvq5GyFbERN1iU"
+    corp-id: "ww51717e2b71d5e2d3"
+    secret: "6ODAmw-8W4t6h9mdzHh2Z4Apwj8mnsyRnjEDZOHdA7k"
+    private-key-path: "privatekey.pem"
+    webhook-url: "https://your-server.com/wecom/archive"
+# token配置
+token:
+    # 令牌自定义标识
+    header: Authorization
+    # 令牌密钥
+    secret: abcdefghijklmnopqrstuvwxyz
+    # 令牌有效期(默认30分钟)
+    expireTime: 180
+openIM:
+    secret: openIM123
+    userID: imAdmin

+ 15 - 0
fs-service/src/main/resources/application-druid-fby.yml

@@ -148,6 +148,21 @@ rocketmq:
         group: test-group
         access-key: ak1243b25nj17d4b2dc1a03 # 替换为实际的 accessKey
         secret-key: sk08a7ea1f9f4b0237 # 替换为实际的 secretKey
+custom:
+    token: "1o62d3YxvdHd4LEUiltnu7sK"
+    encoding-aes-key: "UJfTQ5qKTKlegjkXtp1YuzJzxeHlUKvq5GyFbERN1iU"
+    corp-id: "ww51717e2b71d5e2d3"
+    secret: "6ODAmw-8W4t6h9mdzHh2Z4Apwj8mnsyRnjEDZOHdA7k"
+    private-key-path: "privatekey.pem"
+    webhook-url: "https://your-server.com/wecom/archive"
+# token配置
+token:
+    # 令牌自定义标识
+    header: Authorization
+    # 令牌密钥
+    secret: abcdefghijklmnopqrstuvwxyz
+    # 令牌有效期(默认30分钟)
+    expireTime: 180
 openIM:
     secret: openIM123
     userID: imAdmin

+ 0 - 168
fs-service/src/main/resources/application-druid-hzyy-test.yml

@@ -1,168 +0,0 @@
-# 数据源配置
-spring:
-    profiles:
-        include: config-druid-hzyy,common
-    # redis 配置
-    redis:
-        # 地址
-        host: 127.0.0.1
-        # 端口,默认为6379
-        port: 6379
-        # 数据库索引
-        database: 0
-        # 密码
-        password:
-        # 连接超时时间
-        timeout: 20s
-        lettuce:
-            pool:
-                # 连接池中的最小空闲连接
-                min-idle: 0
-                # 连接池中的最大空闲连接
-                max-idle: 8
-                # 连接池的最大数据库连接数
-                max-active: 8
-                # #连接池最大阻塞等待时间(使用负值表示没有限制)
-                max-wait: -1ms
-    datasource:
-        #        clickhouse:
-        #            type: com.alibaba.druid.pool.DruidDataSource
-        #            driverClassName: com.clickhouse.jdbc.ClickHouseDriver
-        #            url: jdbc:clickhouse://cc-2vc8zzo26w0l7m2l6.public.clickhouse.ads.aliyuncs.com/sop?compress=0&use_server_time_zone=true&use_client_time_zone=false&timezone=Asia/Shanghai
-        #            username: rt_2024
-        #            password: Yzx_19860213
-        #            initialSize: 10
-        #            maxActive: 100
-        #            minIdle: 10
-        #            maxWait: 6000
-        mysql:
-            type: com.alibaba.druid.pool.DruidDataSource
-            driverClassName: com.mysql.cj.jdbc.Driver
-            druid:
-                # 主库数据源
-                master:
-                    url: jdbc:mysql://139.159.133.223:2345/fs_his?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
-                    username: root
-                    password: Ylrztek250218!3@.
-                # 从库数据源
-                slave:
-                    # 从数据源开关/默认关闭
-                    enabled: false
-                    url:
-                    username:
-                    password:
-                # 初始连接数
-                initialSize: 5
-                # 最小连接池数量
-                minIdle: 10
-                # 最大连接池数量
-                maxActive: 20
-                # 配置获取连接等待超时的时间
-                maxWait: 60000
-                # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
-                timeBetweenEvictionRunsMillis: 60000
-                # 配置一个连接在池中最小生存的时间,单位是毫秒
-                minEvictableIdleTimeMillis: 300000
-                # 配置一个连接在池中最大生存的时间,单位是毫秒
-                maxEvictableIdleTimeMillis: 900000
-                # 配置检测连接是否有效
-                validationQuery: SELECT 1 FROM DUAL
-                testWhileIdle: true
-                testOnBorrow: false
-                testOnReturn: false
-                webStatFilter:
-                    enabled: true
-                statViewServlet:
-                    enabled: true
-                    # 设置白名单,不填则允许所有访问
-                    allow:
-                    url-pattern: /druid/*
-                    # 控制台管理用户名和密码
-                    login-username: fs
-                    login-password: 123456
-                filter:
-                    stat:
-                        enabled: true
-                        # 慢SQL记录
-                        log-slow-sql: true
-                        slow-sql-millis: 1000
-                        merge-sql: true
-                    wall:
-                        config:
-                            multi-statement-allow: true
-        sop:
-            type: com.alibaba.druid.pool.DruidDataSource
-            driverClassName: com.mysql.cj.jdbc.Driver
-            druid:
-                # 主库数据源
-                master:
-                    url: jdbc:mysql://139.159.133.223:2345/sop?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
-                    username: root
-                    password: Ylrztek250218!3@.
-                # 初始连接数
-                initialSize: 5
-                # 最小连接池数量
-                minIdle: 10
-                # 最大连接池数量
-                maxActive: 20
-                # 配置获取连接等待超时的时间
-                maxWait: 60000
-                # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
-                timeBetweenEvictionRunsMillis: 60000
-                # 配置一个连接在池中最小生存的时间,单位是毫秒
-                minEvictableIdleTimeMillis: 300000
-                # 配置一个连接在池中最大生存的时间,单位是毫秒
-                maxEvictableIdleTimeMillis: 900000
-                # 配置检测连接是否有效
-                validationQuery: SELECT 1 FROM DUAL
-                testWhileIdle: true
-                testOnBorrow: false
-                testOnReturn: false
-                webStatFilter:
-                    enabled: true
-                statViewServlet:
-                    enabled: true
-                    # 设置白名单,不填则允许所有访问
-                    allow:
-                    url-pattern: /druid/*
-                    # 控制台管理用户名和密码
-                    login-username: fs
-                    login-password: 123456
-                filter:
-                    stat:
-                        enabled: true
-                        # 慢SQL记录
-                        log-slow-sql: true
-                        slow-sql-millis: 1000
-                        merge-sql: true
-                    wall:
-                        config:
-                            multi-statement-allow: true
-rocketmq:
-    name-server: rmq-1243b25nj.rocketmq.gz.public.tencenttdmq.com:8080 # RocketMQ NameServer 地址
-    producer:
-        group: my-producer-group
-        access-key: ak1243b25nj17d4b2dc1a03 # 替换为实际的 accessKey
-        secret-key: sk08a7ea1f9f4b0237 # 替换为实际的 secretKey
-    consumer:
-        group: test-group
-        access-key: ak1243b25nj17d4b2dc1a03 # 替换为实际的 accessKey
-        secret-key: sk08a7ea1f9f4b0237 # 替换为实际的 secretKey
-custom:
-    token: "1o62d3YxvdHd4LEUiltnu7sK"
-    encoding-aes-key: "UJfTQ5qKTKlegjkXtp1YuzJzxeHlUKvq5GyFbERN1iU"
-    corp-id: "ww51717e2b71d5e2d3"
-    secret: "6ODAmw-8W4t6h9mdzHh2Z4Apwj8mnsyRnjEDZOHdA7k"
-    private-key-path: "privatekey.pem"
-    webhook-url: "https://your-server.com/wecom/archive"
-# token配置
-token:
-    # 令牌自定义标识
-    header: Authorization
-    # 令牌密钥
-    secret: abcdefghijklmnopqrstuvwxyz
-    # 令牌有效期(默认30分钟)
-    expireTime: 180
-openIM:
-    secret: openIM123
-    userID: imAdmin

+ 0 - 151
fs-service/src/main/resources/application-druid-jzzx-test.yml

@@ -1,151 +0,0 @@
-# 数据源配置
-spring:
-    profiles:
-        include: config-druid-jzzx,common
-    # redis 配置
-    redis:
-        # 地址
-        host: 127.0.0.1
-        # 端口,默认为6379
-        port: 6379
-        # 数据库索引
-        database: 0
-        # 密码
-        password:
-#        password: Ylrztek250218!3@.
-        # 连接超时时间
-        timeout: 20s
-        lettuce:
-            pool:
-                # 连接池中的最小空闲连接
-                min-idle: 0
-                # 连接池中的最大空闲连接
-                max-idle: 8
-                # 连接池的最大数据库连接数
-                max-active: 8
-                # #连接池最大阻塞等待时间(使用负值表示没有限制)
-                max-wait: -1ms
-    datasource:
-        #        clickhouse:
-        #            type: com.alibaba.druid.pool.DruidDataSource
-        #            driverClassName: com.clickhouse.jdbc.ClickHouseDriver
-        #            url: jdbc:clickhouse://cc-2vc8zzo26w0l7m2l6.public.clickhouse.ads.aliyuncs.com/sop?compress=0&use_server_time_zone=true&use_client_time_zone=false&timezone=Asia/Shanghai
-        #            username: rt_2024
-        #            password: Yzx_19860213
-        #            initialSize: 10
-        #            maxActive: 100
-        #            minIdle: 10
-        #            maxWait: 6000
-        mysql:
-            type: com.alibaba.druid.pool.DruidDataSource
-            driverClassName: com.mysql.cj.jdbc.Driver
-            druid:
-                # 主库数据源
-                master:
-                    url: jdbc:mysql://1.95.34.221:2345/fs_his?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
-                    username: root
-                    password: Ylrztek250218!3@.
-                # 从库数据源
-                slave:
-                    # 从数据源开关/默认关闭
-                    enabled: false
-                    url:
-                    username:
-                    password:
-                # 初始连接数
-                initialSize: 5
-                # 最小连接池数量
-                minIdle: 10
-                # 最大连接池数量
-                maxActive: 20
-                # 配置获取连接等待超时的时间
-                maxWait: 60000
-                # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
-                timeBetweenEvictionRunsMillis: 60000
-                # 配置一个连接在池中最小生存的时间,单位是毫秒
-                minEvictableIdleTimeMillis: 300000
-                # 配置一个连接在池中最大生存的时间,单位是毫秒
-                maxEvictableIdleTimeMillis: 900000
-                # 配置检测连接是否有效
-                validationQuery: SELECT 1 FROM DUAL
-                testWhileIdle: true
-                testOnBorrow: false
-                testOnReturn: false
-                webStatFilter:
-                    enabled: true
-                statViewServlet:
-                    enabled: true
-                    # 设置白名单,不填则允许所有访问
-                    allow:
-                    url-pattern: /druid/*
-                    # 控制台管理用户名和密码
-                    login-username: fs
-                    login-password: 123456
-                filter:
-                    stat:
-                        enabled: true
-                        # 慢SQL记录
-                        log-slow-sql: true
-                        slow-sql-millis: 1000
-                        merge-sql: true
-                    wall:
-                        config:
-                            multi-statement-allow: true
-        sop:
-            type: com.alibaba.druid.pool.DruidDataSource
-            driverClassName: com.mysql.cj.jdbc.Driver
-            druid:
-                # 主库数据源
-                master:
-                    url: jdbc:mysql://1.95.34.221:2345/sop?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
-                    username: root
-                    password: Ylrztek250218!3@.
-                # 初始连接数
-                initialSize: 5
-                # 最小连接池数量
-                minIdle: 10
-                # 最大连接池数量
-                maxActive: 20
-                # 配置获取连接等待超时的时间
-                maxWait: 60000
-                # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
-                timeBetweenEvictionRunsMillis: 60000
-                # 配置一个连接在池中最小生存的时间,单位是毫秒
-                minEvictableIdleTimeMillis: 300000
-                # 配置一个连接在池中最大生存的时间,单位是毫秒
-                maxEvictableIdleTimeMillis: 900000
-                # 配置检测连接是否有效
-                validationQuery: SELECT 1 FROM DUAL
-                testWhileIdle: true
-                testOnBorrow: false
-                testOnReturn: false
-                webStatFilter:
-                    enabled: true
-                statViewServlet:
-                    enabled: true
-                    # 设置白名单,不填则允许所有访问
-                    allow:
-                    url-pattern: /druid/*
-                    # 控制台管理用户名和密码
-                    login-username: fs
-                    login-password: 123456
-                filter:
-                    stat:
-                        enabled: true
-                        # 慢SQL记录
-                        log-slow-sql: true
-                        slow-sql-millis: 1000
-                        merge-sql: true
-                    wall:
-                        config:
-                            multi-statement-allow: true
-rocketmq:
-    name-server: rmq-1243b25nj.rocketmq.gz.public.tencenttdmq.com:8080 # RocketMQ NameServer 地址
-    producer:
-        group: my-producer-group
-        access-key: ak1243b25nj17d4b2dc1a03 # 替换为实际的 accessKey
-        secret-key: sk08a7ea1f9f4b0237 # 替换为实际的 secretKey
-    consumer:
-        group: test-group
-        access-key: ak1243b25nj17d4b2dc1a03 # 替换为实际的 accessKey
-        secret-key: sk08a7ea1f9f4b0237 # 替换为实际的 secretKey

+ 3 - 0
fs-service/src/main/resources/application-druid-kyt.yml

@@ -137,3 +137,6 @@ rocketmq:
     group: test-group
     access-key: ak1243b25nj17d4b2dc1a03 # 替换为实际的 accessKey
     secret-key: sk08a7ea1f9f4b0237 # 替换为实际的 secretKey
+openIM:
+  secret: op
+  userID: im

+ 0 - 150
fs-service/src/main/resources/application-druid-qdtst-test.yml

@@ -1,150 +0,0 @@
-# 数据源配置
-spring:
-    profiles:
-        include: config-druid-qdtst,common
-    # redis 配置
-    redis:
-        # 地址
-        host: 127.0.0.1
-        # 端口,默认为6379
-        port: 6379
-        # 数据库索引
-        database: 0
-        # 密码
-        password:
-        # 连接超时时间
-        timeout: 20s
-        lettuce:
-            pool:
-                # 连接池中的最小空闲连接
-                min-idle: 0
-                # 连接池中的最大空闲连接
-                max-idle: 8
-                # 连接池的最大数据库连接数
-                max-active: 8
-                # #连接池最大阻塞等待时间(使用负值表示没有限制)
-                max-wait: -1ms
-    datasource:
-        #        clickhouse:
-        #            type: com.alibaba.druid.pool.DruidDataSource
-        #            driverClassName: com.clickhouse.jdbc.ClickHouseDriver
-        #            url: jdbc:clickhouse://cc-2vc8zzo26w0l7m2l6.public.clickhouse.ads.aliyuncs.com/sop?compress=0&use_server_time_zone=true&use_client_time_zone=false&timezone=Asia/Shanghai
-        #            username: rt_2024
-        #            password: Yzx_19860213
-        #            initialSize: 10
-        #            maxActive: 100
-        #            minIdle: 10
-        #            maxWait: 6000
-        mysql:
-            type: com.alibaba.druid.pool.DruidDataSource
-            driverClassName: com.mysql.cj.jdbc.Driver
-            druid:
-                # 主库数据源
-                master:
-                    url: jdbc:mysql://119.45.250.185:2345/fs_his?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
-                    username: root
-                    password: Ylrz_1q2w3e4r5t6y
-                # 从库数据源
-                slave:
-                    # 从数据源开关/默认关闭
-                    enabled: false
-                    url:
-                    username:
-                    password:
-                # 初始连接数
-                initialSize: 5
-                # 最小连接池数量
-                minIdle: 10
-                # 最大连接池数量
-                maxActive: 20
-                # 配置获取连接等待超时的时间
-                maxWait: 60000
-                # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
-                timeBetweenEvictionRunsMillis: 60000
-                # 配置一个连接在池中最小生存的时间,单位是毫秒
-                minEvictableIdleTimeMillis: 300000
-                # 配置一个连接在池中最大生存的时间,单位是毫秒
-                maxEvictableIdleTimeMillis: 900000
-                # 配置检测连接是否有效
-                validationQuery: SELECT 1 FROM DUAL
-                testWhileIdle: true
-                testOnBorrow: false
-                testOnReturn: false
-                webStatFilter:
-                    enabled: true
-                statViewServlet:
-                    enabled: true
-                    # 设置白名单,不填则允许所有访问
-                    allow:
-                    url-pattern: /druid/*
-                    # 控制台管理用户名和密码
-                    login-username: fs
-                    login-password: 123456
-                filter:
-                    stat:
-                        enabled: true
-                        # 慢SQL记录
-                        log-slow-sql: true
-                        slow-sql-millis: 1000
-                        merge-sql: true
-                    wall:
-                        config:
-                            multi-statement-allow: true
-        sop:
-            type: com.alibaba.druid.pool.DruidDataSource
-            driverClassName: com.mysql.cj.jdbc.Driver
-            druid:
-                # 主库数据源
-                master:
-                    url: jdbc:mysql://10.206.0.2:3306/sop?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
-                    username: root
-                    password: Ylrz_1q2w3e4r5t6y
-                # 初始连接数
-                initialSize: 5
-                # 最小连接池数量
-                minIdle: 10
-                # 最大连接池数量
-                maxActive: 20
-                # 配置获取连接等待超时的时间
-                maxWait: 60000
-                # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
-                timeBetweenEvictionRunsMillis: 60000
-                # 配置一个连接在池中最小生存的时间,单位是毫秒
-                minEvictableIdleTimeMillis: 300000
-                # 配置一个连接在池中最大生存的时间,单位是毫秒
-                maxEvictableIdleTimeMillis: 900000
-                # 配置检测连接是否有效
-                validationQuery: SELECT 1 FROM DUAL
-                testWhileIdle: true
-                testOnBorrow: false
-                testOnReturn: false
-                webStatFilter:
-                    enabled: true
-                statViewServlet:
-                    enabled: true
-                    # 设置白名单,不填则允许所有访问
-                    allow:
-                    url-pattern: /druid/*
-                    # 控制台管理用户名和密码
-                    login-username: fs
-                    login-password: 123456
-                filter:
-                    stat:
-                        enabled: true
-                        # 慢SQL记录
-                        log-slow-sql: true
-                        slow-sql-millis: 1000
-                        merge-sql: true
-                    wall:
-                        config:
-                            multi-statement-allow: true
-rocketmq:
-    name-server: rmq-1243b25nj.rocketmq.gz.public.tencenttdmq.com:8080 # RocketMQ NameServer 地址
-    producer:
-        group: my-producer-group
-        access-key: ak1243b25nj17d4b2dc1a03 # 替换为实际的 accessKey
-        secret-key: sk08a7ea1f9f4b0237 # 替换为实际的 secretKey
-    consumer:
-        group: test-group
-        access-key: ak1243b25nj17d4b2dc1a03 # 替换为实际的 accessKey
-        secret-key: sk08a7ea1f9f4b0237 # 替换为实际的 secretKey

+ 0 - 148
fs-service/src/main/resources/application-druid-sxjz-test.yml

@@ -1,148 +0,0 @@
-# 数据源配置
-spring:
-    profiles:
-        include: config-druid-sxjz,common
-    # redis 配置
-    redis:
-        host: 127.0.0.1
-        port: 6379
-        # 数据库索引
-        database: 0
-        # 密码
-        password:
-        # 连接超时时间
-        timeout: 10s
-        lettuce:
-            pool:
-                # 连接池中的最小空闲连接
-                min-idle: 0
-                # 连接池中的最大空闲连接
-                max-idle: 8
-                # 连接池的最大数据库连接数
-                max-active: 8
-                # #连接池最大阻塞等待时间(使用负值表示没有限制)
-                max-wait: -1ms
-    datasource:
-        #        clickhouse:
-        #            type: com.alibaba.druid.pool.DruidDataSource
-        #            driverClassName: com.clickhouse.jdbc.ClickHouseDriver
-        #            url: jdbc:clickhouse://1.14.104.71:8123/sop_test?compress=0&use_server_time_zone=true&use_client_time_zone=false&timezone=Asia/Shanghai
-        #            username: rt_2024
-        #            password: Yzx_19860213
-        #            initialSize: 10
-        #            maxActive: 100
-        #            minIdle: 10
-        #            maxWait: 6000
-        mysql:
-            type: com.alibaba.druid.pool.DruidDataSource
-            driverClassName: com.mysql.cj.jdbc.Driver
-            druid:
-                # 主库数据源
-                master:
-                    url: jdbc:mysql://139.155.247.58:2345/fs_his?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
-                    username: root
-                    password: Sxdtcbm@#+!2025
-                # 从库数据源
-                slave:
-                    # 从数据源开关/默认关闭
-                    enabled: false
-                    url:
-                    username:
-                    password:
-                # 初始连接数
-                initialSize: 5
-                # 最小连接池数量
-                minIdle: 10
-                # 最大连接池数量
-                maxActive: 2000
-                # 配置获取连接等待超时的时间
-                maxWait: 60000
-                # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
-                timeBetweenEvictionRunsMillis: 60000
-                # 配置一个连接在池中最小生存的时间,单位是毫秒
-                minEvictableIdleTimeMillis: 300000
-                # 配置一个连接在池中最大生存的时间,单位是毫秒
-                maxEvictableIdleTimeMillis: 900000
-                # 配置检测连接是否有效
-                validationQuery: SELECT 1 FROM DUAL
-                testWhileIdle: true
-                testOnBorrow: false
-                testOnReturn: false
-                webStatFilter:
-                    enabled: true
-                statViewServlet:
-                    enabled: true
-                    # 设置白名单,不填则允许所有访问
-                    allow:
-                    url-pattern: /druid/*
-                    # 控制台管理用户名和密码
-                    login-username: fs
-                    login-password: 123456
-                filter:
-                    stat:
-                        enabled: true
-                        # 慢SQL记录
-                        log-slow-sql: true
-                        slow-sql-millis: 1000
-                        merge-sql: true
-                    wall:
-                        config:
-                            multi-statement-allow: true
-        sop:
-            type: com.alibaba.druid.pool.DruidDataSource
-            driverClassName: com.mysql.cj.jdbc.Driver
-            druid:
-                # 主库数据源
-                master:
-                    url: jdbc:mysql://139.155.247.58:2345/fs_his_sop?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
-                    username: root
-                    password: Sxdtcbm@#+!2025
-                # 初始连接数
-                initialSize: 5
-                # 最小连接池数量
-                minIdle: 10
-                # 最大连接池数量
-                maxActive: 200
-                # 配置获取连接等待超时的时间
-                maxWait: 60000
-                # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
-                timeBetweenEvictionRunsMillis: 60000
-                # 配置一个连接在池中最小生存的时间,单位是毫秒
-                minEvictableIdleTimeMillis: 300000
-                # 配置一个连接在池中最大生存的时间,单位是毫秒
-                maxEvictableIdleTimeMillis: 900000
-                # 配置检测连接是否有效
-                validationQuery: SELECT 1 FROM DUAL
-                testWhileIdle: true
-                testOnBorrow: false
-                testOnReturn: false
-                webStatFilter:
-                    enabled: true
-                statViewServlet:
-                    enabled: true
-                    # 设置白名单,不填则允许所有访问
-                    allow:
-                    url-pattern: /druid/*
-                    # 控制台管理用户名和密码
-                    login-username: fs
-                    login-password: 123456
-                filter:
-                    stat:
-                        enabled: true
-                        # 慢SQL记录
-                        log-slow-sql: true
-                        slow-sql-millis: 1000
-                        merge-sql: true
-                    wall:
-                        config:
-                            multi-statement-allow: true
-rocketmq:
-    name-server: rmq-1243b25nj.rocketmq.gz.public.tencenttdmq.com:8080 # RocketMQ NameServer 地址
-    producer:
-        group: my-producer-group
-        access-key: ak1243b25nj17d4b2dc1a03 # 替换为实际的 accessKey
-        secret-key: sk08a7ea1f9f4b0237 # 替换为实际的 secretKey
-    consumer:
-        group: voice-group
-        access-key: ak1243b25nj17d4b2dc1a03 # 替换为实际的 accessKey
-        secret-key: sk08a7ea1f9f4b0237 # 替换为实际的 secretKey

+ 12 - 0
fs-service/src/main/resources/application-druid-sxjz.yml

@@ -146,3 +146,15 @@ rocketmq:
         group: voice-group
         access-key: ak1243b25nj17d4b2dc1a03 # 替换为实际的 accessKey
         secret-key: sk08a7ea1f9f4b0237 # 替换为实际的 secretKey
+
+# token配置
+token:
+    # 令牌自定义标识
+    header: Authorization
+    # 令牌密钥
+    secret: abcdefghijklmnopqrstuvwxyz
+    # 令牌有效期(默认30分钟)
+    expireTime: 180
+openIM:
+    secret: openIM123
+    userID: imAdmin

+ 0 - 153
fs-service/src/main/resources/application-druid-xfk-test.yml

@@ -1,153 +0,0 @@
-# 数据源配置
-spring:
-    profiles:
-        include: config-druid-xfk,common
-    # redis 配置
-    redis:
-        # 地址
-        host: 127.0.0.1
-        # 端口,默认为6379
-        port: 6379
-        # 数据库索引
-        database: 0
-        # 密码
-        password:
-        # 连接超时时间
-        timeout: 20s
-        lettuce:
-            pool:
-                # 连接池中的最小空闲连接
-                min-idle: 0
-                # 连接池中的最大空闲连接
-                max-idle: 8
-                # 连接池的最大数据库连接数
-                max-active: 8
-                # #连接池最大阻塞等待时间(使用负值表示没有限制)
-                max-wait: -1ms
-    datasource:
-        #        clickhouse:
-        #            type: com.alibaba.druid.pool.DruidDataSource
-        #            driverClassName: com.clickhouse.jdbc.ClickHouseDriver
-        #            url: jdbc:clickhouse://cc-2vc8zzo26w0l7m2l6.public.clickhouse.ads.aliyuncs.com/sop?compress=0&use_server_time_zone=true&use_client_time_zone=false&timezone=Asia/Shanghai
-        #            username: rt_2024
-        #            password: Yzx_19860213
-        #            initialSize: 10
-        #            maxActive: 100
-        #            minIdle: 10
-        #            maxWait: 6000
-        mysql:
-            type: com.alibaba.druid.pool.DruidDataSource
-            driverClassName: com.mysql.cj.jdbc.Driver
-            druid:
-                # 主库数据源
-                master:
-                    url: jdbc:mysql://119.45.13.86:8866/fs_his?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
-                    username: root
-                    password: Ylrz_1q2w3e4r5t6y
-                # 从库数据源
-                slave:
-                    # 从数据源开关/默认关闭
-                    enabled: false
-                    url:
-                    username:
-                    password:
-                # 初始连接数
-                initialSize: 5
-                # 最小连接池数量
-                minIdle: 10
-                # 最大连接池数量
-                maxActive: 20
-                # 配置获取连接等待超时的时间
-                maxWait: 60000
-                # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
-                timeBetweenEvictionRunsMillis: 60000
-                # 配置一个连接在池中最小生存的时间,单位是毫秒
-                minEvictableIdleTimeMillis: 300000
-                # 配置一个连接在池中最大生存的时间,单位是毫秒
-                maxEvictableIdleTimeMillis: 900000
-                # 配置检测连接是否有效
-                validationQuery: SELECT 1 FROM DUAL
-                testWhileIdle: true
-                testOnBorrow: false
-                testOnReturn: false
-                webStatFilter:
-                    enabled: true
-                statViewServlet:
-                    enabled: true
-                    # 设置白名单,不填则允许所有访问
-                    allow:
-                    url-pattern: /druid/*
-                    # 控制台管理用户名和密码
-                    login-username: fs
-                    login-password: 123456
-                filter:
-                    stat:
-                        enabled: true
-                        # 慢SQL记录
-                        log-slow-sql: true
-                        slow-sql-millis: 1000
-                        merge-sql: true
-                    wall:
-                        config:
-                            multi-statement-allow: true
-        sop:
-            type: com.alibaba.druid.pool.DruidDataSource
-            driverClassName: com.mysql.cj.jdbc.Driver
-            druid:
-                # 主库数据源
-                master:
-                    url: jdbc:mysql://119.45.13.86:8866/sop?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
-                    username: root
-                    password: Ylrz_1q2w3e4r5t6y
-                # 初始连接数
-                initialSize: 5
-                # 最小连接池数量
-                minIdle: 10
-                # 最大连接池数量
-                maxActive: 20
-                # 配置获取连接等待超时的时间
-                maxWait: 60000
-                # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
-                timeBetweenEvictionRunsMillis: 60000
-                # 配置一个连接在池中最小生存的时间,单位是毫秒
-                minEvictableIdleTimeMillis: 300000
-                # 配置一个连接在池中最大生存的时间,单位是毫秒
-                maxEvictableIdleTimeMillis: 900000
-                # 配置检测连接是否有效
-                validationQuery: SELECT 1 FROM DUAL
-                testWhileIdle: true
-                testOnBorrow: false
-                testOnReturn: false
-                webStatFilter:
-                    enabled: true
-                statViewServlet:
-                    enabled: true
-                    # 设置白名单,不填则允许所有访问
-                    allow:
-                    url-pattern: /druid/*
-                    # 控制台管理用户名和密码
-                    login-username: fs
-                    login-password: 123456
-                filter:
-                    stat:
-                        enabled: true
-                        # 慢SQL记录
-                        log-slow-sql: true
-                        slow-sql-millis: 1000
-                        merge-sql: true
-                    wall:
-                        config:
-                            multi-statement-allow: true
-rocketmq:
-    name-server: rmq-1243b25nj.rocketmq.gz.public.tencenttdmq.com:8080 # RocketMQ NameServer 地址
-    producer:
-        group: my-producer-group
-        access-key: ak1243b25nj17d4b2dc1a03 # 替换为实际的 accessKey
-        secret-key: sk08a7ea1f9f4b0237 # 替换为实际的 secretKey
-    consumer:
-        group: test-group
-        access-key: ak1243b25nj17d4b2dc1a03 # 替换为实际的 accessKey
-        secret-key: sk08a7ea1f9f4b0237 # 替换为实际的 secretKey
-openIM:
-    secret: op
-    userID: im

+ 17 - 1
fs-service/src/main/resources/mapper/company/CompanyMoneyLogsMapper.xml

@@ -31,7 +31,23 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         <include refid="selectCompanyMoneyLogsVo"/>
         where logs_id = #{logsId}
     </select>
-        
+    <select id="selectCompanyRedPackageListVO" resultType="com.fs.company.domain.CompanyRedPackage">
+        select sum(l.amount) as totalAmount,u.nick_name as nickName,c.company_name as companyName
+        from fs_course_red_packet_log l
+        LEFT JOIN company_user u on l.company_user_id =u.user_id
+        left join company c on l.company_id = c.company_id
+        where
+        u.user_id is not null and l.status=1
+        <if test="companyId != null">
+            and l.company_id = #{companyId}
+        </if>
+        <if test="dateTime != null">
+            and DATE_FORMAT(l.create_time,'%Y-%m-%d') like concat(#{dateTime}, '%')
+        </if>
+        GROUP BY l.company_user_id
+        order by c.company_id,u.user_id
+    </select>
+
     <insert id="insertCompanyMoneyLogs" parameterType="CompanyMoneyLogs" useGeneratedKeys="true" keyProperty="logsId">
         insert into company_money_logs
         <trim prefix="(" suffix=")" suffixOverrides=",">

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

@@ -26,7 +26,6 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         <where>
             <if test="title != null  and title != ''"> and title like concat('%', #{title}, '%') </if>
             <if test="sort != null "> and sort = #{sort}</if>
-            <if test="userId != null "> and user_id = #{userId}</if>
             <if test="type != null "> and type = #{type}</if>
             <if test="questionType != null "> and question_type = #{questionType}</if>
             <if test="questionSubType != null "> and question_sub_type = #{questionSubType}</if>
@@ -55,7 +54,6 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="createBy != null">create_by,</if>
             <if test="questionType != null">question_type,</if>
             <if test="questionSubType != null">question_sub_type,</if>
-            <if test="userId != null">user_id,</if>
          </trim>
         <trim prefix="values (" suffix=")" suffixOverrides=",">
             <if test="title != null">#{title},</if>
@@ -68,7 +66,6 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="createBy != null">#{createBy},</if>
             <if test="questionType != null">#{questionType},</if>
             <if test="questionSubType != null">#{questionSubType},</if>
-            <if test="userId != null">#{userId},</if>
          </trim>
     </insert>
 
@@ -83,8 +80,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         answer,
         create_by,
         question_type,
-        question_sub_type,
-        user_id
+        question_sub_type
         )
         VALUES
         <foreach collection="list" item="item" separator=",">
@@ -98,8 +94,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             #{item.answer, jdbcType=CLOB},
             #{item.createBy, jdbcType=VARCHAR},
             #{item.questionType, jdbcType=VARCHAR},
-            #{item.questionSubType, jdbcType=VARCHAR},
-            #{item.userId, jdbcType=BIGINT}
+            #{item.questionSubType, jdbcType=VARCHAR}
             )
         </foreach>
     </insert>

+ 1 - 0
fs-service/src/main/resources/mapper/course/FsCourseRedPacketLogMapper.xml

@@ -38,6 +38,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="companyUserId != null "> and company_user_id = #{companyUserId}</if>
             <if test="companyId != null "> and company_id = #{companyId}</if>
             <if test="amount != null "> and amount = #{amount}</if>
+            <if test="status != null "> and `status` = #{status}</if>
             <if test="qwUserId != null  and qwUserId != ''"> and qw_user_id = #{qwUserId}</if>
         </where>
     </select>

+ 0 - 11
fs-service/src/main/resources/mapper/course/FsUserCourseMapper.xml

@@ -85,7 +85,6 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="talentId != null "> and talent_id = #{talentId}</if>
             <if test="isNext != null "> and is_next = #{isNext}</if>
             <if test="isPrivate != null "> and is_private = #{isPrivate}</if>
-            <if test="userId != null "> and user_id = #{userId}</if>
         </where>
     </select>
 
@@ -194,7 +193,6 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="isPrivate != null">is_private,</if>
             <if test="secondImg != null">second_img,</if>
             <if test="companyIds != null">company_ids,</if>
-            <if test="userId != null">user_id,</if>
         </trim>
         <trim prefix="values (" suffix=")" suffixOverrides=",">
             <if test="cateId != null">#{cateId},</if>
@@ -234,7 +232,6 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="isPrivate != null">#{isPrivate},</if>
             <if test="secondImg != null">#{secondImg},</if>
             <if test="companyIds != null">#{companyIds},</if>
-            <if test="userId != null">#{userId},</if>
          </trim>
     </insert>
 
@@ -312,12 +309,4 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 <!--        ORDER BY-->
 <!--        c.course_id-->
 <!--    </select>-->
-
-    <select id="selectFsUserCourseAllList" resultType="com.fs.his.vo.OptionsVO">
-        select course_id dict_value, course_name dict_label,img_url dict_imgUrl  from fs_user_course
-        where is_del = 0 and is_private = 1
-        <if test="userId != null">
-            and user_id = #{userId}
-        </if>
-    </select>
 </mapper>

+ 0 - 3
fs-service/src/main/resources/mapper/course/FsUserCourseTrainingCampMapper.xml

@@ -28,9 +28,6 @@
             <if test="params.userId != null and params.userId != ''">
                 and cu.user_id = #{params.userId}
             </if>
-            <if test="params.userId != null and params.userId != ''">
-                and ctc.user_id like concat('%',#{params.userId},'%')
-            </if>
         </where>
         group by ctc.training_camp_id, ctc.training_camp_name, ctc.order_number
         order by

+ 0 - 7
fs-service/src/main/resources/mapper/course/FsUserCourseVideoMapper.xml

@@ -35,7 +35,6 @@
         <result property="viewStartTime"    column="view_start_time"    />
         <result property="viewEndTime"    column="view_end_time"    />
         <result property="lastJoinTime"    column="last_join_time"    />
-        <result property="userId" column="user_id" />
         <result property="projectId"    column="project_id"    />
     </resultMap>
 
@@ -59,7 +58,6 @@
             <if test="questionBankId != null "> and question_bank_id = #{questionBankId}</if>
             <if test="userId != null "> and user_id = #{userId}</if>
             <if test="projectId != null "> and project_id = #{projectId}</if>
-            <if test="userId != null "> and user_id = #{userId}</if>
         </where>
     </select>
 
@@ -100,7 +98,6 @@
             <if test="viewStartTime != null">view_start_time,</if>
             <if test="viewEndTime != null">view_end_time,</if>
             <if test="lastJoinTime != null">last_join_time,</if>
-            <if test="userId != null">user_id,</if>
             <if test="projectId != null">project_id,</if>
             <if test="isProduct != null">is_product,</if>
             <if test="productId != null">product_id,</if>
@@ -141,7 +138,6 @@
             <if test="productId != null">#{productId},</if>
             <if test="listingStartTime != null">#{listingStartTime},</if>
             <if test="listingEndTime != null">#{listingEndTime},</if>
-            <if test="userId != null">#{userId},</if>
             <if test="projectId != null">#{projectId},</if>
         </trim>
     </insert>
@@ -164,7 +160,6 @@
         file_size,
         file_key,
         is_transcode,
-        user_id,
         project_id
         )
         values
@@ -186,7 +181,6 @@
             #{item.fileSize},
             #{item.fileKey},
             #{item.isTranscode},
-            #{item.userId},
             #{item.projectId}
             )
         </foreach>
@@ -228,7 +222,6 @@
             <if test="productId != null">product_id = #{productId},</if>
             <if test="listingStartTime != null">listing_start_time = #{listingStartTime},</if>
             <if test="listingEndTime != null">listing_end_time = #{listingEndTime},</if>
-            <if test="userId != null">user_id = #{userId},</if>
             <if test="projectId != null">project_id = #{projectId},</if>
         </trim>
         where video_id = #{videoId}

+ 0 - 3
fs-service/src/main/resources/mapper/course/FsVideoResourceMapper.xml

@@ -18,9 +18,6 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         <if test="params.typeId != null">
             and rr.type_id = #{params.typeId}
         </if>
-        <if test="params.userId != null">
-            and rr.user_id = #{params.userId}
-        </if>
         <if test="params.typeSubId != null">
             and rr.type_sub_id = #{params.typeSubId}
         </if>

+ 8 - 5
fs-service/src/main/resources/mapper/his/FsStoreOrderMapper.xml

@@ -892,7 +892,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             </if>
 
         </where>
-
+        ${maps.params.dataScope}
         ORDER BY
 
         <if test="maps.sortField == 'companyUserName'">
@@ -913,7 +913,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         <if test="maps.sortField == null or maps.sortField == ''">
             so.order_id desc
         </if>
-        ${maps.params.dataScope}
+
     </select>
     <select id="selectFsStoreOrderListVOByErpAccount" resultType="com.fs.his.vo.FsStoreOrderListVO">
         select so.*,st.store_name,us.nick_name,us.phone,d.doctor_name,p.patient_name,p.prescribe_code,c.company_name,
@@ -1098,12 +1098,15 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="maps.erpPhoneNumber != null and maps.erpPhoneNumber != ''">
                 and so.erp_phone like concat(#{maps.erpPhoneNumber},'%')
             </if>
-            <if test="maps.erpAccount != null and maps.erpAccount != ''">
+            <if test="maps.erpAccount != null and maps.erpAccount != '未分拣' and maps.erpAccount != ''">
                 and df.login_account like #{maps.erpAccount}
             </if>
+            <if test="maps.erpAccount == '未分拣'">
+                and ( df.login_account is null or df.login_account like '')
+            </if>
 
         </where>
-
+        ${maps.params.dataScope}
         ORDER BY
 
         <if test="maps.sortField == 'companyUserName'">
@@ -1124,7 +1127,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         <if test="maps.sortField == null or maps.sortField == ''">
             so.order_id desc
         </if>
-        ${maps.params.dataScope}
+
     </select>
     <select id="selectFsStoreOrderByFsUserId" resultMap="FsStoreOrderResult">
         <include refid="selectFsStoreOrderVo"/>

+ 39 - 9
fs-service/src/main/resources/mapper/statis/FsStatisQwWatchMapper.xml

@@ -245,7 +245,9 @@
             ifnull(sum(remind_pending_num),0) as remind_pending_num,
             ifnull(sum(remind_processed_num),0) as remind_processed_num,
             (case when sum(send_num)>=sum(registered_num) then ROUND(SUM(registered_num) * 1.0 / SUM(send_num), 4) else 0 end) as reg_rate,
-            (case when sum(send_num)>=sum(completed_num) then ROUND(SUM(completed_num) * 1.0 / SUM(send_num), 4) else 0 end) as finished_rate
+            (case when sum(send_num)>=sum(completed_num) then ROUND(SUM(completed_num) * 1.0 / SUM(send_num), 4) else 0 end) as finished_rate,
+            ifnull(sum(traffic_sum,0)) as traffic_sum,
+            ifnull(sum(reg_num,0)) as reg_num
         from fs_statis_qw_watch
         <where>
             <if test="startDate != null and endDate != null">
@@ -288,7 +290,9 @@
         ifnull(sum(watch.remind_pending_num),0) as remind_pending_num,
         ifnull(sum(watch.remind_processed_num),0) as remind_processed_num,
         (case when sum(watch.send_num)>=sum(watch.registered_num) then ROUND(SUM(watch.registered_num) * 1.0 / SUM(watch.send_num), 4) else 0 end) as reg_rate,
-        (case when sum(watch.send_num)>=sum(watch.completed_num) then ROUND(SUM(watch.completed_num) * 1.0 / SUM(watch.send_num), 4) else 0 end) as finished_rate
+        (case when sum(watch.send_num)>=sum(watch.completed_num) then ROUND(SUM(watch.completed_num) * 1.0 / SUM(watch.send_num), 4) else 0 end) as finished_rate,
+        ifnull(sum(traffic_sum,0)) as traffic_sum,
+        ifnull(sum(reg_num,0)) as reg_num
         from fs_statis_qw_watch watch
         left join company_dept dept on watch.dept_id=dept.dept_id
         left join company_user cu on watch.company_user_id=cu.user_id
@@ -321,7 +325,7 @@
             #{item.deletedNum,jdbcType=BIGINT}, #{item.orderNum,jdbcType=BIGINT}, #{item.orderMoneyTotal,jdbcType=DECIMAL},
             #{item.redPackageMoneyTotal,jdbcType=DECIMAL}, #{item.callNum,jdbcType=BIGINT}, #{item.receivePassNum,jdbcType=BIGINT},
             #{item.receiveNotNum,jdbcType=BIGINT}, #{item.callTimeTotal,jdbcType=BIGINT}, #{item.remindPendingNum,jdbcType=BIGINT},
-            #{item.remindProcessedNum,jdbcType=BIGINT}
+            #{item.remindProcessedNum,jdbcType=BIGINT},#{item.trafficSum,jdbcType=BIGINT},#{item.regNum,jdbcType=BIGINT}
             )
         </foreach>
     </insert>
@@ -349,7 +353,9 @@
                 remind_pending_num,
                 remind_processed_num,
                 qw_repeat_num,
-                user_repeat_num
+                user_repeat_num,
+                traffic_sum,
+                reg_num
             )
             WITH extended_temp AS (
             -- 原始temp表数据
@@ -406,7 +412,9 @@
             IFNULL(qw_work.remind_pending_num, 0) as remind_pending_num,
             IFNULL(qw_work.remind_processed_num, 0) as remind_processed_num,
             IFNULL(contact.qw_repeat_num,0) as qw_repeat_num,
-            IFNULL(contact.user_repeat_num,0) as user_repeat_num
+            IFNULL(contact.user_repeat_num,0) as user_repeat_num,
+            IFNULL(traffic.traffic_sum,0) as traffic_sum,
+            IFNULL(fs_user.reg_num,0) as reg_num
             FROM extended_temp temp
             LEFT JOIN (
             SELECT
@@ -439,7 +447,7 @@
             AND contact.status IN (4, 5, 7)
             AND contact.update_time >= #{startTime}
             AND contact.update_time < #{endTime}
-            GROUP BY qw_user_id, company_user_id
+            GROUP BY company_user_id,qw_user_id
             ) contact ON contact.qw_user_id = temp.qw_user_id
             AND contact.company_user_id = temp.company_user_id
 
@@ -455,7 +463,7 @@
             AND company_user_id IS NOT NULL
             AND create_time >= #{startTime}
             AND create_time < #{endTime}
-            GROUP BY company_user_id
+            GROUP BY company_user_id,qw_user_id
             ) stats_order ON temp.company_user_id = stats_order.company_user_id
             AND temp.qw_user_id = '-1'
             -- 红包数
@@ -468,7 +476,7 @@
             WHERE status = 1
             AND create_time >= #{startTime}
             AND create_time < #{endTime}
-            GROUP BY company_user_id
+            GROUP BY company_user_id,qw_user_id
             ) redp ON temp.company_user_id = redp.company_user_id
             AND temp.qw_user_id = '-1'
             -- 通话统计(总拨打数(可以后面两项相加)、接通数、未接通数、通话时长)
@@ -498,7 +506,29 @@
             GROUP BY company_user_id, qw_user_id
             ) qw_work ON temp.company_user_id = qw_work.company_user_id
             AND temp.qw_user_id = qw_work.qw_user_id
-
+                -- 流量统计
+            LEFT JOIN (
+                select
+                    company_user_id,
+                    qw_user_id,
+                    SUM(internet_traffic) as traffic_sum
+                from fs_course_traffic_log
+                where create_time >= #{startTime}
+                  AND create_time < #{endTime}
+                GROUP BY company_user_id, qw_user_id
+            )traffic ON temp.company_user_id = traffic.company_user_id
+                AND temp.qw_user_id = traffic.qw_user_id
+                -- 注册人数
+            LEFT JOIN (
+                select company_user_id,
+                       qw_user_id,
+                       count(user_id) as reg_num
+                from fs_user
+                WHERE create_time >= #{startTime}
+                  AND create_time < #{endTime}
+                GROUP BY company_user_id, qw_user_id
+            ) fs_user ON temp.company_user_id = fs_user.company_user_id
+                AND temp.qw_user_id = fs_user.qw_user_id
         ]]>
     </insert>
 

+ 10 - 0
fs-service/src/main/resources/pay/alipay.properties

@@ -0,0 +1,10 @@
+alipay.appId=2021003175603885
+alipay.privateKey=MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCQ6KdwrikzvXJOVJGqqD1wqNmnbatbkjguDhzkPYIVYX4A8lDEhcz0mQfJsnTAjebZMgSny8KqvK+8JnePwk+U25ZKxY/78dBmB1m4hxoDYuixULOpBlIU76H2e77KYV2ZUIbUKNrkcZ/fEh10+/u5msVE/67u389dQApIMAWPAjcRALWuJleUpfBSe6RwP/JtRY6C8mhnIXPpd2viEu8Lkxjs37HnWN/9KWfZIvdxrx/PjDu3DKi1kiSS+FWwGeQUwrYOk6yclWseI+A3dohwsvVzd/7X3OmmGph6S1Sv8Luoq7KlZ25uvlFiAYxV2fTyJ1gTRomuqzBG+4l/n9BjAgMBAAECggEAAdt5ifAxhwA+ntJmq5FMeE0xvPui3qGZJr33kNVY/X0qaEiy0FIGtnvfpa4r4OvwsYf6l0v9SsLwXbEAh08uRfIqkvrFRa1rxmMBu2O/6Zsy8FLgeqIiGzKXGNmtMFrfID/v+ngrlhH+wpUw23b/Wvmo3aGJVHZ56fAQMayr5ZFUw0F6FktB0lGQjLw2yS6nwy6GvsCA3KeclP3AQGPxVZC3uuw2oVDkqHBBeHk0L5XA3x8DgeJ73zsWlWRD7dPOrhjiLzFl9WdGQobP2TTNzVH3uolUtxkC4o9I8B6BdARqLDn2yqalF6MzzlOlKTo8/I+htQ8qxcudQzZ+2CjiQQKBgQDDYzrwnk0DPWDp2lThZ8gy/c4dX/RgIH+YndW9DYhDkTH6Bhb+bGKFWL4zods3RIEWZgQWzKTXzm7UhoN6QOu/0xl3l4OIyd9OjTaX9BTm2mT3IB7mHq+7trJgHldZiP325uZr1pH4hJ9FW/tOYKP5sA2fy1ka2+t/tKbjHVJzPQKBgQC93KICFYjWTHw6L/6t4jzyE1co0sOivfRf/ObKNzmv5Qe8RKr4f/vZBHHvuh9SOMd/ZLDKbqzEMJkB4iP/XjGk5SWARTWUVzY21hYBjYthjJ9ZmbrZM8Ys2M2N38edvFJn6fUeZFbCBNm7GbJIqdAgMhB+xnEkKwMGQyqTSgEMHwKBgQCoWxpwNpa5Uevt1LkKuDgi59rwKLwTEC2hvW5sRfrB7ZwYiaLKe22w5LSPHModJyPrvt+LHa50XWXWLkmfz8zTLvxkteMavIdz0e3WpPRVrp0M61p0gsB9iIDOnZY6ifX7Bx5IkUyZzPzH8Ofrsw3XmcFDjR4sLI8RLQIX9C4VKQKBgQCzNCbuVKkdrH+s5FQ8h8gCrWKdM6JYX3bjiu/DejDG5yRP/XhqqVJrWhi4rzKVBua2RbHgwGntm/kvn+VeSegNvgOReMHDzDVtuNB4ksM2Rea6SbHlBUtOVSxfdxMQvQoC7v7futFwu+dPBEgU8cNyQA71uhRckQR/yrHK6BTo/QKBgGyYgL97kQX1CR4LDXVMn2ebhIcadjVCKlZe2v1gtd9HkYh5zqJhtNsFO5HgBB+tW1/EFD+wHeZ+5LcYgNc6fU6gJEvnYG0ezUGfnrNg2oKW22oDE9h2tPap6BYIJboohiY0gq6pgu3wEAwCEwtRjYYNwr4ZDRM9Wq/RlgBalY5S
+alipay.publicKey=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxq6z6GPljO9YCrOptYhWSXO5ts4phovkcVXHc2NBLBq8p1jS/pyQj5k3Oay0lRI3cE7Apl6b/nqMCa1sxg5P/muqNAr6S1wy4X/uvWZwMKK2Woe6OJqfY7DLiRqjpQ4Tp5GIgY5AI7D91hHbQHTRVzKz4SwCwNTHriVuzfXgqnoq6kaQn/EtP0edf1qqb5gdBcK4Z9SgZLLxXMXqiCfUcvkfgjEwDq0HIbX/DdrPvJ9WmoT0uIWTMWk3fx549wnmG0rCxwERldFVJ5Rvn4Q3PzHkt1YITmxigryPMyDfk+U5CHysJ8O2cBtlpNGBRYZyh0Ul+eCcA1zI0fWimZORfQIDAQAB
+alipay.appCertPath=C:/App/cert/alipay/appCertPublicKey_2021002106618710.crt
+alipay.aliPayCertPath=C:/App/cert/alipay/alipayCertPublicKey_RSA2.crt
+alipay.aliPayRootCertPath=C:/App/cert/alipay/alipayRootCert.crt
+alipay.serverUrl=https://openapi.alipay.com/gateway.do
+alipay.domain=https://api.yjf.runtzh.com
+alipay.returnDomain=http://alipay.yjf.runtzh.com
+

+ 8 - 0
fs-service/src/main/resources/pay/alipay1.properties

@@ -0,0 +1,8 @@
+alipay.appId=2021001183651266
+alipay.privateKey=MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDHxLTvAARsNy8Vx3UAD+N1xc0bME315mB+p7tuhGxqoGgOhFDQ4ozKs/HQ+lRXzzLSkKvZMQqK3GRP4mx4ziihZ8qLSzyxKC6yRVujMd4igq26/POERUlzbAl50SBWGDiVxMJBidtvq0EmoFYGzalix8gD3QhitQGeUl93k1omNDDFP7qQEGhUMA3BHVj4JTwMHT7s5EzZ/189d00OC3atYzF5mcswTYCEJY7WIPDCB9+1Hr63jYufTSlDYkZBwvObxQU7sLlj64gd2u/n/QydunXp1PwZN5aUnTE3MW0Gzx+MeIf7myB3DFfOqTP6mC/sXSVGnbO1Agnfohl6gEQpAgMBAAECggEBAIkV7oe3/lD4iYIrjpmNTazrIPYQbt9YyU0A83lCvFdrXhzgJclCPhV36HBc6HYdhKXEi3kO00o5NUkwevlnl7AzVmXCKpLznR/OwrS5qtMJ1AhmPwG8vkvLjrEelk8ebe4wyJFK9d+qqJnGG2KtzRgxOouUKYX66nJn2oVnA80EeVNJQ3PqMbT2Q6p/sm+BJVb54t9KoPyuXe6MqHr9fWiUoJ47bE/JgqQg9pSs9lHRvqWcCIBnUY+Y4ZuE1HsFWg+mtLt+qFktFO+3xbj0jhrbzqsVR/pjHq6wxumidA9yaSMEvRqECi7x6VTH7OquOYMNCZW5Fdw+KMg9mvrx+lECgYEA/IcvtH62bQxHg9uOuuNFFPGeyuhYJk950PDdWmBKXOIfLNm1PL6UcY8vSP4rWpk4VrXdt0bt9suME+zmXWwymFwESKl0Kmcy1c3hsFBKnJApfxbULzDUFXGbMd/0WqPBibx98iLxpdlHxREg/vcuOB+ZUIPI7px5dNkgL5JfR70CgYEAyoPS+ahUmr/57kaxt3TpsDDIotvVT+k3hD3MSmBZu2AXPcPFapqydWdBHHfhq1GnEN7QvfYQOgBRF3+l9WRuKBefmu8sLsPzHbLoVBBK594yBmBQmy6C+g83/zOqTxK57YLk9abtc9Y6ssXQGkR2/DRCYm1CtqQmB/fElKlPDt0CgYBnJYzNy+gVuKtJZ5fwLD6eZGb4+FhxJYtbVdcEQEp/j/kt56sIqcuWaubkiLUKp4UEnfp3DyjJ4rBPvzcFN9metA8n4tdJLqfr/tFNpC4lrxjUCW4X7HjkXWgHwjNcBoFaEjzbd3x+wrZ2/x0cJ7igQf/sjDe5hv5xRPLJm58BfQKBgF+iky4tDQ8rW7bnkaNmRblbwFQQZpLfOsVrfZ8eEyIGhdM4MXFfbqk8wqXUAzEpVTEFWCRtIEqTvbfQIypYbCDozwmWqxHGnXfH9ilErGsFJjCWqVovQ9EdAL+2wVWoLT95kfBkDTynzX6BJf5RmLMPZs4edOPVbtRScHYX4mrNAoGBAMVkGQuSIM4Mf/bMvEqPMc9GpYJ6tA6BqBsLY9yyXnArHaR9dGvKmN59+JmxM9sYCXunhtyLu83bkB2XtfIUGj8TYJxWUxvAwcx8JAE5qb6E5oStKbxb0hKh5CG59gqFlAVpcqMIwpeCDQhBin5AlMTgrmV8S6gTBp0efHTn9G4N
+alipay.publicKey=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArqkO4WGHLHufhdMMOsckp964jUWNncwY9r4XB2HVEeHIDOcThp61/TJXGKxmQctAQ9CDNK1aP4SPWHd3rItN8HIX1Fo+oXsDkHrlRqh5p2DOdvmsaGbceyCT/OF4nX+km/WJ9TXBQ3SaI5h8xqESeX0srs0j7QjXafGQrprO2wlih84Ri2FbaDIJvlReZcJZLpxlYBKGXfepp1wvBEMmHH66JArWZ2w03zaFODW7vbEZZplKOZMijPE0V2SUsqwqqbPajKaO3cXf/pE9bzIGi9VLcpr0cWSkzdEUF0yQ1w/dxkdfMdgyurSb7CpuYU7/QEHWNJp5w5euGySDS1U4xQIDAQAB
+alipay.appCertPath=
+alipay.aliPayCertPath=
+alipay.aliPayRootCertPath=
+alipay.serverUrl=https://openapi.alipay.com/gateway.do
+alipay.domain=http://http://api.qinpeilian.com/

BIN
fs-service/src/main/resources/pay/cert/apiclient_cert.p12


+ 26 - 0
fs-service/src/main/resources/pay/cert/apiclient_cert.pem

@@ -0,0 +1,26 @@
+-----BEGIN CERTIFICATE-----
+MIIEazCCA9SgAwIBAgIDPfFVMA0GCSqGSIb3DQEBBQUAMIGKMQswCQYDVQQGEwJD
+TjESMBAGA1UECBMJR3Vhbmdkb25nMREwDwYDVQQHEwhTaGVuemhlbjEQMA4GA1UE
+ChMHVGVuY2VudDEMMAoGA1UECxMDV1hHMRMwEQYDVQQDEwpNbXBheW1jaENBMR8w
+HQYJKoZIhvcNAQkBFhBtbXBheW1jaEB0ZW5jZW50MB4XDTE2MDgyMjEwMDAyN1oX
+DTI2MDgyMDEwMDAyN1owgZsxCzAJBgNVBAYTAkNOMRIwEAYDVQQIEwlHdWFuZ2Rv
+bmcxETAPBgNVBAcTCFNoZW56aGVuMRAwDgYDVQQKEwdUZW5jZW50MQ4wDAYDVQQL
+EwVNTVBheTEwMC4GA1UEAxQn5YyX5Lqs5b+r5a6i5pyN56eR5oqA5Y+R5bGV5pyJ
+6ZmQ5YWs5Y+4MREwDwYDVQQEEwgxMzk5MzgzMjCCASIwDQYJKoZIhvcNAQEBBQAD
+ggEPADCCAQoCggEBAMRbFxBzC0GQ14Hxh4Uspdt3B7mQSAsa2hLvqWYsPYXbQ9Rh
+Jb/pdUOF9zwh4i9CTrWLqSazgs7Rqf7EEyhdT08KDQbF9uDRHW3m/XSGb8XyQKX0
+yu8yEUDH6SvUGQQ3U4DOOsHooa9jTIZeohAtwe9+GQX2WjRzjr3RlW2DIyTGwjYi
+QB5CU1uivt+tfEDW+wP4gjnWecShYPfeK1uIybinFzmy4tUGGuNl7N9H4IrMi2TT
+BpqMGbEukoDjzYv4h23MPuh6f1AHGpsI39BJJs8TjYeccMIrOqzXSv1bcRVsH+FZ
+4AkYhgeCt6MudedjGy5J9IEU957esxmXtSuDt10CAwEAAaOCAUYwggFCMAkGA1Ud
+EwQCMAAwLAYJYIZIAYb4QgENBB8WHSJDRVMtQ0EgR2VuZXJhdGUgQ2VydGlmaWNh
+dGUiMB0GA1UdDgQWBBTOrb+vqp/rqP6DZntwZEmzL+ickTCBvwYDVR0jBIG3MIG0
+gBQ+BSb2ImK0FVuIzWR+sNRip+WGdKGBkKSBjTCBijELMAkGA1UEBhMCQ04xEjAQ
+BgNVBAgTCUd1YW5nZG9uZzERMA8GA1UEBxMIU2hlbnpoZW4xEDAOBgNVBAoTB1Rl
+bmNlbnQxDDAKBgNVBAsTA1dYRzETMBEGA1UEAxMKTW1wYXltY2hDQTEfMB0GCSqG
+SIb3DQEJARYQbW1wYXltY2hAdGVuY2VudIIJALtUlyu8AOhXMA4GA1UdDwEB/wQE
+AwIGwDAWBgNVHSUBAf8EDDAKBggrBgEFBQcDAjANBgkqhkiG9w0BAQUFAAOBgQBC
+n8MEDVIVlyC2jkRfy4UezLlbnGTkYb+Nb4oMZRvIjNTFzqQ+6SOPKEqlU0FOZwuI
+pr+pDG+H484PQjt6b8ftUOBuKKeaMDMauRz2jqXJkKWcDa4U/CJ+/CboolU4T0xO
+Lp+zNqa7epBvU3HQtX4MEzZEnI5auPVde9nsJbo2QA==
+-----END CERTIFICATE-----

+ 28 - 0
fs-service/src/main/resources/pay/cert/apiclient_key.pem

@@ -0,0 +1,28 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDEWxcQcwtBkNeB
+8YeFLKXbdwe5kEgLGtoS76lmLD2F20PUYSW/6XVDhfc8IeIvQk61i6kms4LO0an+
+xBMoXU9PCg0Gxfbg0R1t5v10hm/F8kCl9MrvMhFAx+kr1BkEN1OAzjrB6KGvY0yG
+XqIQLcHvfhkF9lo0c4690ZVtgyMkxsI2IkAeQlNbor7frXxA1vsD+II51nnEoWD3
+3itbiMm4pxc5suLVBhrjZezfR+CKzItk0waajBmxLpKA482L+IdtzD7oen9QBxqb
+CN/QSSbPE42HnHDCKzqs10r9W3EVbB/hWeAJGIYHgrejLnXnYxsuSfSBFPee3rMZ
+l7Urg7ddAgMBAAECggEAZt2FhrOOOQoFLGj44xaRyRhhbqAcbdziU7tEFmekz2Qf
+87n1CcXnDbm33MOvd6yYCVmiAslWBL0n/nR/yMyhSLnuOxcoj3xdm37AVvQ6yAty
+PL6yNX8YNMTF7ZUOifvl/fuMIpuZYIV3yIj5A9rE149K0qnNdd73749FZfqmRZQD
+rwh4Xh8M+mj8CulpGsjwKVfUrCWsXaVh9pL7XNMYXBRnGdrCFOs7uPjAUcOZlXjx
+LboQqjmVbveeGJ2lptRjDu5y934T7msQPugss/aCZAbaNN1RklBGJ3FtxgRAQ8z5
+zKCaWzDFyXGWENY/+ZHai9pHK2QS0IPhb+qV/qiYzQKBgQDgaWNOqb14QwbwshFr
+C3Ib5s2XqhTFBTxrtJceWUZZiHDL3Z5ecSPSeBREpxLn/miVIXBc/zyGGF5E2SPB
+zPuj9xrtI8HlxETZG4NuUbgqfFdPUKwroAPMvhqM7ZaanYqRiVTkvmVHtuL4aFk3
+LCKuhjHiSkW2ZaKlgqAkdcGGAwKBgQDf/renwmIC7Lh6sJewsRKe3h3UhzG0XW8t
+HIbx7b5cqKRTrdkPeBLN4w64D37kEK9mmoLsYkZuHA2YJndDGyu6+R2tI69s3vyr
+8hfJBDK0WaVEps2BUQ5KXDrbquYVbBGA6Q7anpVhekXILKBQRxUd7UaRqTvCL04R
+bH7NZzN/HwKBgE5j4gG/f2T8HPeFbFo1NFYUyKp7CihMjO+etM8wJkfuRmCgeMrK
+wNWrhoD4z7zkfMnjVWnW6uB4sK1iIIB5R0nebrR5sii958LjPoUR3MBSkPku2AWh
+LtKdcY7bC6nU8GuoSlRhQeXMN/rIEKoaK79FNzWx9ioh1K/2MlSqIcDbAoGADBQi
+NyumOV4mfIc1RtPlmyeDGEjKB13aduZI6JbXYwu9AL4pLEpfSTbrPkWnpAi6TKAc
+Wz7ZaWqd2QyJ9dZrP0Pbs9Buz0IfAe6mFbLiQRNsdA1Cm6yRRrU+f0Xx7knLj9YB
+dQyEJaOAS9EMPAf5PYnj+krT7B686Peexti/0CUCgYB9uACIaTlN0XQvoXuFktv4
+4xqyOLCfTZW38e1UJ4bqyOJUP0EKfo/03j8Lp/vsZmCK2bIdudG+4rZbuiQXOe31
+cfGo7dQhCorOlrUig0CWwq8oXPbKmvOO7K+UGnK5e46BUbopxU1dTwhxAUA6hbcb
+mFh3iSvhn4JJG2ddomXY3A==
+-----END PRIVATE KEY-----

+ 18 - 0
fs-service/src/main/resources/pay/cert/证书使用说明.txt

@@ -0,0 +1,18 @@
+欢迎使用微信支付!
+附件中的三份文件(证书pkcs12格式、证书pem格式、证书密钥pem格式),为接口中强制要求时需携带的证书文件。
+证书属于敏感信息,请妥善保管不要泄露和被他人复制。
+不同开发语言下的证书格式不同,以下为说明指引:
+    证书pkcs12格式(apiclient_cert.p12)
+        包含了私钥信息的证书文件,为p12(pfx)格式,由微信支付签发给您用来标识和界定您的身份
+        部分安全性要求较高的API需要使用该证书来确认您的调用身份
+        windows上可以直接双击导入系统,导入过程中会提示输入证书密码,证书密码默认为您的商户ID(如:10010000)
+    证书pem格式(apiclient_cert.pem)
+        从apiclient_cert.p12中导出证书部分的文件,为pem格式,请妥善保管不要泄漏和被他人复制
+        部分开发语言和环境,不能直接使用p12文件,而需要使用pem,所以为了方便您使用,已为您直接提供
+        您也可以使用openssl命令来自己导出:openssl pkcs12 -clcerts -nokeys -in apiclient_cert.p12 -out apiclient_cert.pem
+    证书密钥pem格式(apiclient_key.pem)
+        从apiclient_cert.p12中导出密钥部分的文件,为pem格式
+        部分开发语言和环境,不能直接使用p12文件,而需要使用pem,所以为了方便您使用,已为您直接提供
+        您也可以使用openssl命令来自己导出:openssl pkcs12 -nocerts -in apiclient_cert.p12 -out apiclient_key.pem
+备注说明:  
+        由于绝大部分操作系统已内置了微信支付服务器证书的根CA证书,  2018年3月6日后, 不再提供CA证书文件(rootca.pem)下载 

+ 8 - 0
fs-service/src/main/resources/pay/wxpay.properties

@@ -0,0 +1,8 @@
+wxpay.appId=wxbe53e91d9ad11ca6
+wxpay.appSecret=58d70c9be43047ef3275339a3f4b5ee0
+wxpay.mchId=1581878681
+wxpay.partnerKey=8cab128997a3547c1363b0898b877f38
+wxpay.certPath=pay/cert/apiclient_cert.p12
+wxpay.domain= https://api.hospital.ifeiyu100.com
+
+

+ 9 - 0
fs-service/src/main/resources/pay/wxpay_v3.properties

@@ -0,0 +1,9 @@
+v3.appId=\u5E94\u7528\u7F16\u53F7
+v3.keyPath=key.pem
+v3.certPath=cert.pem
+v3.certP12Path=cert.p12
+v3.platformCertPath=wx_cert.pem
+v3.mchId=\u5FAE\u4FE1\u5546\u6237\u53F7
+v3.apiKey3= Api-v3 \u5BC6\u94A5
+v3.apiKey= Api \u5BC6\u94A5
+v3.domain=  http://qbhdat.natappfree.cc

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

@@ -142,7 +142,7 @@ public class IndexController extends AppBaseController {
 
 	@ApiOperation("企业理念")
 	@GetMapping("/getConcept")
-	@springfox.documentation.annotations.Cacheable("getConcept")
+	@Cacheable("getConcept")
 	public R getConcept(HttpServletRequest request){
 		String json=configService.selectConfigByKey("store.concept");
 		ConceptConfig config = JSONUtil.toBean(json, ConceptConfig.class);

+ 12 - 3
fs-user-app/src/main/java/com/fs/app/controller/UserController.java

@@ -129,11 +129,20 @@ public class UserController extends  AppBaseController {
         }
     }
 
-    @Login
     @ApiOperation("检测是否登录")
     @GetMapping("/checkLogin")
-    public R checkLogin(){
-        return R.ok("认证成功");
+    public R checkLogin(HttpServletRequest request){
+        if(StringUtils.isEmpty(getUserId())){
+            //未登录
+            return R.error("未登录");
+        }
+        else{
+            //登录
+            String token = jwtUtils.generateToken(Long.parseLong(getUserId()));
+            Map<String,Object> map=new HashMap<>();
+            map.put("token",token);
+            return R.ok("认证成功").put("userId",getUserId()).put("token",token);
+        }
     }
 
     @Login

+ 235 - 0
fs-user-app/src/main/java/com/fs/app/controller/WxH5MpController.java

@@ -0,0 +1,235 @@
+package com.fs.app.controller;
+
+import cn.binarywang.wx.miniapp.api.WxMaService;
+import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
+import cn.hutool.core.date.DateTime;
+import com.fs.app.param.FsUserLoginByMpParam;
+import com.fs.app.utils.JwtUtils;
+import com.fs.common.core.domain.R;
+import com.fs.common.core.redis.RedisCache;
+import com.fs.company.domain.Company;
+import com.fs.company.domain.CompanyUser;
+import com.fs.company.service.ICompanyService;
+import com.fs.company.service.ICompanyUserService;
+import com.fs.core.config.WxMaConfiguration;
+import com.fs.course.domain.FsUserCompanyUser;
+import com.fs.course.mapper.FsCourseWatchLogMapper;
+import com.fs.course.service.IFsUserCompanyUserService;
+import com.fs.his.domain.FsUser;
+import com.fs.his.domain.FsUserWx;
+import com.fs.his.service.IFsUserService;
+import com.fs.his.service.IFsUserWxService;
+import com.fs.qw.mapper.QwExternalContactMapper;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.extern.slf4j.Slf4j;
+import me.chanjar.weixin.common.bean.WxOAuth2UserInfo;
+import me.chanjar.weixin.common.bean.oauth2.WxOAuth2AccessToken;
+import me.chanjar.weixin.common.error.WxErrorException;
+import me.chanjar.weixin.mp.api.WxMpService;
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.validation.Valid;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+import java.util.concurrent.TimeUnit;
+
+@Api("会员-h5-微信相关接口(后面不需要这个接口了,再删除))")
+@RestController
+@RequestMapping("/app/wx/h5/mp")
+@Slf4j
+public class WxH5MpController {
+    Logger logger = LoggerFactory.getLogger(getClass());
+    @Autowired
+    private WxMpService wxMpService;
+
+    @Autowired
+    private IFsUserService userService;
+
+    @Autowired
+    JwtUtils jwtUtils;
+    @Autowired
+    RedisCache redisCache;
+
+    @Autowired
+    FsCourseWatchLogMapper fsCourseWatchLogMapper;
+    @Autowired
+    QwExternalContactMapper qwExternalContactMapper;
+    @Autowired
+    ICompanyService companyService;
+    @Autowired
+    ICompanyUserService companyUserService;
+    @Autowired
+    private IFsUserCompanyUserService userCompanyUserService;
+    @Autowired
+    private IFsUserWxService fsUserWxService;
+
+    @ApiOperation("课程分享链接公众号登录")
+    @PostMapping("/loginByMp")
+    public R loginByMp(@Valid @RequestBody FsUserLoginByMpParam param) {
+        log.info("=====================进入小程序授权登录, 入参: {}", param);
+
+        // 参数校验
+        if (StringUtils.isBlank(param.getCode())) {
+            return R.error("code不存在");
+        }
+
+        // 公司状态校验
+        Company company = companyService.selectCompanyById(param.getCompanyId());
+        if (company == null || company.getStatus() == 0) {
+            return R.error("注册失败团队已停用,或不存在!");
+        }
+
+        // 客服状态校验
+        CompanyUser companyUser = companyUserService.selectCompanyUserById(param.getCompanyUserId());
+        if (companyUser == null || "1".equals(companyUser.getStatus())) {
+            return R.error("注册失败客服已停用,或不存在!");
+        }
+
+        try {
+            // 获取微信用户信息
+            WxOAuth2AccessToken wxMpOAuth2AccessToken = wxMpService.getOAuth2Service().getAccessToken(param.getCode());
+            WxOAuth2UserInfo wxMpUser = wxMpService.getOAuth2Service().getUserInfo(wxMpOAuth2AccessToken, null);
+
+            // 处理用户信息
+            FsUser user = processUserInfo(wxMpUser, company,companyUser);
+
+            // 处理用户与公司的关系
+            processUserCompanyRelationship(user, param, companyUser, company);
+
+            // 检查用户是否已绑定其他销售
+            FsUserCompanyUser userCompanyUser = userCompanyUserService.selectByUserIdAndProjectId(user.getUserId(), param.getProjectId());
+            if (Objects.nonNull(userCompanyUser) && !param.getCompanyUserId().equals(userCompanyUser.getCompanyUserId())){
+                return R.error(500, "该用户("+user.getUserId() + ")已成为其他销售会员");
+            }
+
+            // 生成token并返回结果
+            return generateLoginResult(user);
+        } catch (WxErrorException e) {
+            this.logger.error(e.getMessage(), e);
+            return R.error("授权失败," + e.getMessage());
+        }
+    }
+
+    private FsUser processUserInfo(WxOAuth2UserInfo wxMpUser, Company company,CompanyUser companyUser) {
+        FsUser user = userService.selectFsUserByUnionId(wxMpUser.getUnionId());
+
+        if (user != null) {
+            // 更新现有用户信息
+            FsUser userUpdate = new FsUser();
+            userUpdate.setUserId(user.getUserId());
+            userUpdate.setMpOpenId(wxMpUser.getOpenid());
+            userUpdate.setUnionId(wxMpUser.getUnionId());
+            userUpdate.setUpdateTime(new DateTime());
+            userUpdate.setNickName(wxMpUser.getNickname());
+            userUpdate.setAvatar(wxMpUser.getHeadImgUrl());
+            userService.updateFsUser(userUpdate);
+            return userUpdate;
+        } else {
+            // 创建新用户
+            FsUser newUser = new FsUser();
+            newUser.setNickName(wxMpUser.getNickname());
+            newUser.setAvatar(wxMpUser.getHeadImgUrl());
+            newUser.setStatus(1);
+            newUser.setMpOpenId(wxMpUser.getOpenid());
+            newUser.setCompanyId(company.getCompanyId());
+            newUser.setCompanyUserId(companyUser.getUserId());
+            newUser.setUnionId(wxMpUser.getUnionId());
+            newUser.setCreateTime(new Date());
+            newUser.setStatus(company != null && company.getFsUserIsDefaultBlack() == 1 ? 0 : 1);
+            userService.insertFsUser(newUser);
+            return newUser;
+        }
+    }
+
+    private void processUserCompanyRelationship(FsUser user, FsUserLoginByMpParam param,
+                                                CompanyUser companyUser, Company company) {
+        if ((companyUser.getIsAllowedAllRegister() == null || companyUser.getIsAllowedAllRegister() == 1)
+                && companyUser.getIsNeedRegisterMember() != null && companyUser.getIsNeedRegisterMember() != 1) {
+            int defaultStatus = (company != null && company.getFsUserIsDefaultBlack() == 1) ? 0 : 1;
+            userCompanyUserService.bindRelationship(
+                    user.getUserId(),
+                    param.getProjectId(),
+                    companyUser.getCompanyId(),
+                    companyUser.getUserId(),
+                    defaultStatus
+            );
+        }
+    }
+
+    private R generateLoginResult(FsUser user) {
+        log.info("打印用户信息--------------------》{}",user);
+        String token = jwtUtils.generateToken(user.getUserId());
+        redisCache.setCacheObject("token:" + user.getUserId(), token, 604800, TimeUnit.SECONDS);
+
+        Map<String, Object> result = new HashMap<>();
+        result.put("token", token);
+        result.put("user", user);
+        return R.ok(result);
+    }
+
+    private R handleWxErrorException(WxErrorException e) {
+        if (e.getError().getErrorCode() == 40163) {
+            return R.error(40163, e.getError().getErrorMsg());
+        }
+        return R.error("授权失败," + e.getMessage());
+    }
+
+
+    @ApiOperation("处理用户与小程序的绑定")
+    @PostMapping("/handleFsUserWx")
+    public R handleFsUserWx(@RequestBody FsUserLoginByMpParam param) {
+        try {
+            final WxMaService wxService = WxMaConfiguration.getMaService(param.getAppId());
+            //获取微信用户信息
+            WxMaJscode2SessionResult session = wxService.getUserService().getSessionInfo(param.getCode());
+
+            FsUser user = userService.selectFsUserById(param.getUserId());
+            handleFsUserWx(user, param, session);
+            return R.ok();
+        } catch (WxErrorException e) {
+            if (e.getError().getErrorCode() == 40163) {
+                return R.error(40163, e.getError().getErrorMsg());
+            } else {
+                return R.error("获取用户信息失败," + e.getMessage());
+            }
+        }
+
+    }
+    private void handleFsUserWx(FsUser user, FsUserLoginByMpParam param, WxMaJscode2SessionResult session) {
+        if (user == null) return;
+        // 尝试更新
+        boolean updated = fsUserWxService.lambdaUpdate()
+                .eq(FsUserWx::getFsUserId, user.getUserId())
+                .eq(FsUserWx::getAppId, param.getAppId())
+                .eq(FsUserWx::getOpenId, session.getOpenid())
+                .set(FsUserWx::getCompanyId, user.getCompanyId())
+                .set(FsUserWx::getUnionId, session.getUnionid() == null ? "" : session.getUnionid())
+                .set(FsUserWx::getUpdateTime, new Date())
+                .update();
+
+        // 如果更新失败(记录不存在),则插入
+        if (!updated) {
+            FsUserWx fsUserWx = new FsUserWx();
+            fsUserWx.setType(1);
+            fsUserWx.setFsUserId(user.getUserId());
+            fsUserWx.setCompanyId(user.getCompanyId());
+            fsUserWx.setAppId(param.getAppId());
+            fsUserWx.setOpenId(session.getOpenid());
+            fsUserWx.setUnionId(session.getUnionid() == null ? "" : session.getUnionid());
+            fsUserWx.setCreateTime(new Date());
+            fsUserWx.setUpdateTime(new Date());
+            fsUserWxService.save(fsUserWx);
+        }
+    }
+
+}

+ 9 - 0
fs-user-app/src/main/java/com/fs/app/controller/WxPayController.java

@@ -2,6 +2,8 @@ package com.fs.app.controller;
 
 
 import cn.hutool.json.JSONUtil;
+import com.fs.company.service.ICompanyRechargeService;
+import com.fs.core.config.WxPayProperties;
 import com.fs.course.config.RedPacketConfig;
 import com.fs.course.domain.FsCourseRedPacketLog;
 import com.fs.course.service.IFsCourseProductOrderService;
@@ -26,6 +28,7 @@ import com.github.binarywang.wxpay.constant.WxPayConstants;
 import com.github.binarywang.wxpay.exception.WxPayException;
 import com.github.binarywang.wxpay.service.WxPayService;
 import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl;
+import com.github.binarywang.wxpay.util.SignUtils;
 import com.google.gson.Gson;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
@@ -41,6 +44,8 @@ import org.springframework.web.bind.annotation.*;
 
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
+import java.util.HashMap;
+import java.util.Map;
 
 @Api("微信支付接口")
 @RestController
@@ -76,7 +81,11 @@ public class WxPayController {
     @Autowired
     private IFsCourseProductOrderService courseProductOrderService;
 
+    @Autowired
+    ICompanyRechargeService rechargeService;
 
+    @Autowired
+    private WxPayProperties wxPayProperties;
     /**
      * 微信回调
      * 回调接口代码内部自动校验结果签名和业务代码

+ 1 - 1
fs-user-app/src/main/java/com/fs/app/controller/course/CourseQwController.java

@@ -84,7 +84,7 @@ public class CourseQwController extends AppBaseController {
         }
         return R.ok().put("data",course);
     }
-    @ApiOperation("查询全部公域的课程")
+    @ApiOperation("查询公域的视频")
     @GetMapping("/getAppletCourseVideo")
     public R getAppletCourseVideo(@RequestParam("courseId") Long courseId)
     {

+ 6 - 0
fs-user-app/src/main/java/com/fs/app/param/FsUserLoginByMpParam.java

@@ -24,4 +24,10 @@ public class FsUserLoginByMpParam implements Serializable {
     @ApiModelProperty(value = "项目ID")
     private Long projectId;
 
+    private String appId;
+
+    /**
+     * 用户id
+     */
+    private Long userId;
 }

+ 12 - 12
fs-user-app/src/main/java/com/fs/framework/config/RedisConfig.java

@@ -31,18 +31,18 @@ import java.time.Duration;
 public class RedisConfig extends CachingConfigurerSupport
 {
 
-    @Bean
-    public RedisCacheManager cacheManager(RedisConnectionFactory connectionFactory) {
-        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
-                .entryTtl(Duration.ofSeconds(30))
-                .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))
-                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()))
-                .disableCachingNullValues();
-
-        return RedisCacheManager.builder(connectionFactory)
-                .cacheDefaults(config)
-                .build();
-    }
+//    @Bean
+//    public RedisCacheManager cacheManager(RedisConnectionFactory connectionFactory) {
+//        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
+//                .entryTtl(Duration.ofSeconds(30))
+//                .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))
+//                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()))
+//                .disableCachingNullValues();
+//
+//        return RedisCacheManager.builder(connectionFactory)
+//                .cacheDefaults(config)
+//                .build();
+//    }
 
     @Bean
     @SuppressWarnings(value = { "unchecked", "rawtypes" })