Browse Source

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

caoliqin 1 week ago
parent
commit
16f975b1c1
90 changed files with 2135 additions and 311 deletions
  1. 115 0
      fs-admin/src/main/java/com/fs/course/controller/FsCoursePlaySourceConfigController.java
  2. 2 8
      fs-admin/src/main/java/com/fs/course/controller/FsCourseTrafficLogController.java
  3. 97 0
      fs-admin/src/main/java/com/fs/fastGpt/FastgptChatArtificialWordsController.java
  4. 23 4
      fs-admin/src/main/java/com/fs/his/controller/FsArticleCateController.java
  5. 7 2
      fs-admin/src/main/java/com/fs/his/controller/FsDoctorArticleController.java
  6. 10 8
      fs-admin/src/main/java/com/fs/his/controller/FsPackageCateController.java
  7. 20 4
      fs-admin/src/main/java/com/fs/web/controller/system/SysLoginController.java
  8. 23 0
      fs-common/src/main/java/com/fs/common/utils/CloudHostUtils.java
  9. 10 0
      fs-common/src/main/java/com/fs/common/utils/spring/SpringUtils.java
  10. 1 1
      fs-company-app/src/main/java/com/fs/app/config/WebMvcConfig.java
  11. 5 1
      fs-company-app/src/main/java/com/fs/app/controller/AppBaseController.java
  12. 22 75
      fs-company/src/main/java/com/fs/company/controller/common/Test.java
  13. 7 0
      fs-company/src/main/java/com/fs/company/controller/qw/QwExternalContactController.java
  14. 5 0
      fs-company/src/main/java/com/fs/company/controller/store/FsUserCouponController.java
  15. 1 1
      fs-company/src/main/java/com/fs/framework/config/SecurityConfig.java
  16. 6 2
      fs-doctor-app/src/main/java/com/fs/app/controller/DoctorArticleController.java
  17. 7 1
      fs-doctor-app/src/main/java/com/fs/app/controller/DoctorController.java
  18. 1 5
      fs-doctor-app/src/main/java/com/fs/app/controller/InquiryOrderController.java
  19. 1 1
      fs-qwhook/src/main/resources/application.yml
  20. 62 15
      fs-service/src/main/java/com/fs/core/config/WxMaConfiguration.java
  21. 79 0
      fs-service/src/main/java/com/fs/course/domain/FsCoursePlaySourceConfig.java
  22. 17 0
      fs-service/src/main/java/com/fs/course/mapper/FsCoursePlaySourceConfigMapper.java
  23. 1 0
      fs-service/src/main/java/com/fs/course/mapper/FsUserCourseVideoRedPackageMapper.java
  24. 45 0
      fs-service/src/main/java/com/fs/course/param/FsCoursePlaySourceConfigCreateParam.java
  25. 42 0
      fs-service/src/main/java/com/fs/course/param/FsCoursePlaySourceConfigEditParam.java
  26. 3 0
      fs-service/src/main/java/com/fs/course/param/FsCourseWatchLogListParam.java
  27. 3 0
      fs-service/src/main/java/com/fs/course/param/PeriodCountParam.java
  28. 16 0
      fs-service/src/main/java/com/fs/course/service/IFsCoursePlaySourceConfigService.java
  29. 27 0
      fs-service/src/main/java/com/fs/course/service/impl/FsCoursePlaySourceConfigServiceImpl.java
  30. 28 26
      fs-service/src/main/java/com/fs/course/service/impl/FsCourseQuestionBankServiceImpl.java
  31. 32 5
      fs-service/src/main/java/com/fs/course/service/impl/FsCourseWatchLogServiceImpl.java
  32. 26 12
      fs-service/src/main/java/com/fs/course/service/impl/FsUserCourseOrderServiceImpl.java
  33. 1 0
      fs-service/src/main/java/com/fs/course/service/impl/FsUserCoursePeriodDaysServiceImpl.java
  34. 16 3
      fs-service/src/main/java/com/fs/course/service/impl/FsUserCourseVideoServiceImpl.java
  35. 28 12
      fs-service/src/main/java/com/fs/course/service/impl/FsUserVipOrderServiceImpl.java
  36. 49 0
      fs-service/src/main/java/com/fs/course/vo/FsCoursePlaySourceConfigVO.java
  37. 2 0
      fs-service/src/main/java/com/fs/course/vo/FsCourseWatchLogListVO.java
  38. 62 0
      fs-service/src/main/java/com/fs/fastGpt/mapper/FastgptChatArtificialWordsMapper.java
  39. 62 0
      fs-service/src/main/java/com/fs/fastGpt/service/IFastgptChatArtificialWordsService.java
  40. 106 0
      fs-service/src/main/java/com/fs/fastGpt/service/impl/FastgptChatArtificialWordsServiceImpl.java
  41. 1 1
      fs-service/src/main/java/com/fs/his/dto/PayConfigDTO.java
  42. 1 1
      fs-service/src/main/java/com/fs/his/mapper/FsPackageMapper.java
  43. 3 0
      fs-service/src/main/java/com/fs/his/param/FsPackageCateUParam.java
  44. 3 0
      fs-service/src/main/java/com/fs/his/param/FsUserCouponSendParam.java
  45. 3 0
      fs-service/src/main/java/com/fs/his/param/WxSendRedPacketParam.java
  46. 1 0
      fs-service/src/main/java/com/fs/his/service/IFsPackageCateService.java
  47. 1 1
      fs-service/src/main/java/com/fs/his/service/impl/FsExportTaskServiceImpl.java
  48. 7 0
      fs-service/src/main/java/com/fs/his/service/impl/FsPackageCateServiceImpl.java
  49. 25 8
      fs-service/src/main/java/com/fs/his/service/impl/FsPackageOrderServiceImpl.java
  50. 7 0
      fs-service/src/main/java/com/fs/his/service/impl/FsPackageServiceImpl.java
  51. 26 9
      fs-service/src/main/java/com/fs/his/service/impl/FsStoreOrderServiceImpl.java
  52. 52 28
      fs-service/src/main/java/com/fs/his/service/impl/FsStorePaymentServiceImpl.java
  53. 6 5
      fs-service/src/main/java/com/fs/his/service/impl/FsUserCouponServiceImpl.java
  54. 18 7
      fs-service/src/main/java/com/fs/his/service/impl/FsUserIntegralLogsServiceImpl.java
  55. 9 5
      fs-service/src/main/java/com/fs/his/service/impl/FsUserServiceImpl.java
  56. 1 1
      fs-service/src/main/java/com/fs/qw/mapper/QwUserMapper.java
  57. 1 1
      fs-service/src/main/java/com/fs/qw/service/impl/QwUserVoiceLogServiceImpl.java
  58. 1 0
      fs-service/src/main/java/com/fs/qw/vo/QwUserVoiceLogTotalVo.java
  59. 1 1
      fs-service/src/main/java/com/fs/sop/mapper/QwSopLogsMapper.java
  60. 3 2
      fs-service/src/main/java/com/fs/sop/service/impl/QwSopTempServiceImpl.java
  61. 6 5
      fs-service/src/main/java/com/fs/sop/service/impl/SopUserLogsInfoServiceImpl.java
  62. 1 1
      fs-service/src/main/resources/application-config-druid-hdt.yml
  63. 2 1
      fs-service/src/main/resources/application-config-druid-qdtst.yml
  64. 87 0
      fs-service/src/main/resources/application-config-druid-syysy-test.yml
  65. 4 4
      fs-service/src/main/resources/application-config-druid-syysy.yml
  66. 1 0
      fs-service/src/main/resources/application-dev.yml
  67. 172 0
      fs-service/src/main/resources/application-druid-jzzx-test.yml
  68. 5 1
      fs-service/src/main/resources/application-druid-jzzx.yml
  69. 168 0
      fs-service/src/main/resources/application-druid-qdtst-test.yml
  70. 18 0
      fs-service/src/main/resources/application-druid-qdtst.yml
  71. 166 0
      fs-service/src/main/resources/application-druid-syysy-test.yml
  72. 11 11
      fs-service/src/main/resources/application-druid-syysy.yml
  73. 1 1
      fs-service/src/main/resources/application-druid-yzt.yml
  74. 33 0
      fs-service/src/main/resources/db/20250821-点播播放源配置改造.sql
  75. 20 0
      fs-service/src/main/resources/mapper/course/FsCoursePlaySourceConfigMapper.xml
  76. 5 1
      fs-service/src/main/resources/mapper/course/FsCourseWatchLogMapper.xml
  77. 76 0
      fs-service/src/main/resources/mapper/fastGpt/FastgptChatArtificialWordsMapper.xml
  78. 1 0
      fs-service/src/main/resources/mapper/his/FsArticleCateMapper.xml
  79. 2 2
      fs-service/src/main/resources/mapper/his/FsUserMapper.xml
  80. 22 14
      fs-service/src/main/resources/mapper/qw/QwUserVoiceLogMapper.xml
  81. 0 1
      fs-user-app/src/main/java/com/fs/FsUserAppApplication.java
  82. 18 0
      fs-user-app/src/main/java/com/fs/app/controller/AppLoginController.java
  83. 6 1
      fs-user-app/src/main/java/com/fs/app/controller/CouponController.java
  84. 34 6
      fs-user-app/src/main/java/com/fs/app/controller/InquiryOrderController.java
  85. 2 2
      fs-user-app/src/main/java/com/fs/app/controller/PackageController.java
  86. 18 0
      fs-user-app/src/main/java/com/fs/app/controller/UserController.java
  87. 2 0
      fs-user-app/src/main/java/com/fs/app/controller/WxUserController.java
  88. 1 1
      fs-user-app/src/main/java/com/fs/app/controller/store/StoreOrderScrmController.java
  89. 4 1
      fs-user-app/src/main/java/com/fs/framework/aspectj/UserOperationLogAspect.java
  90. 9 2
      fs-user-app/src/main/java/com/fs/framework/config/SecurityConfig.java

+ 115 - 0
fs-admin/src/main/java/com/fs/course/controller/FsCoursePlaySourceConfigController.java

@@ -0,0 +1,115 @@
+package com.fs.course.controller;
+
+import com.baomidou.mybatisplus.core.conditions.Wrapper;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+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.bean.BeanUtils;
+import com.fs.course.domain.FsCoursePlaySourceConfig;
+import com.fs.course.param.FsCoursePlaySourceConfigCreateParam;
+import com.fs.course.param.FsCoursePlaySourceConfigEditParam;
+import com.fs.course.service.IFsCoursePlaySourceConfigService;
+import com.fs.course.vo.FsCoursePlaySourceConfigVO;
+import com.github.pagehelper.PageHelper;
+import lombok.AllArgsConstructor;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import javax.validation.Valid;
+import java.time.LocalDateTime;
+import java.util.*;
+
+@RestController
+@RequestMapping("/course/playSourceConfig")
+@AllArgsConstructor
+public class FsCoursePlaySourceConfigController extends BaseController {
+
+    private final IFsCoursePlaySourceConfigService fsCoursePlaySourceConfigService;
+
+    @PreAuthorize("@ss.hasPermi('course:playSourceConfig:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(@RequestParam(required = false) String name,
+                              @RequestParam(required = false) String appid,
+                              @RequestParam(required = false, defaultValue = "1") Integer pageNum,
+                              @RequestParam(required = false, defaultValue = "10") Integer pageSize) {
+        Map<String, Object> params = new HashMap<>();
+        params.put("name", name);
+        params.put("appid", appid);
+
+        PageHelper.startPage(pageNum, pageSize);
+        List<FsCoursePlaySourceConfigVO> list = fsCoursePlaySourceConfigService.selectCoursePlaySourceConfigVOListByMap(params);
+        return getDataTable(list);
+    }
+
+    @PreAuthorize("@ss.hasPermi('course:playSourceConfig:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable Long id) {
+        FsCoursePlaySourceConfig config = fsCoursePlaySourceConfigService.getById(id);
+        if (Objects.isNull(config)) {
+            return AjaxResult.success(null);
+        }
+
+        FsCoursePlaySourceConfigVO configVO = new FsCoursePlaySourceConfigVO();
+        BeanUtils.copyProperties(config, configVO);
+        return AjaxResult.success(configVO);
+    }
+
+    @PreAuthorize("@ss.hasPermi('course:playSourceConfig:add')")
+    @Log(title = "点播播放源配置", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@Valid @RequestBody FsCoursePlaySourceConfigCreateParam param) {
+        Wrapper<FsCoursePlaySourceConfig> queryWrapper = Wrappers.<FsCoursePlaySourceConfig>lambdaQuery()
+                .eq(FsCoursePlaySourceConfig::getAppid, param.getAppid())
+                .eq(FsCoursePlaySourceConfig::getIsDel, 0);
+        if (fsCoursePlaySourceConfigService.count(queryWrapper) > 0) {
+            return AjaxResult.error("appid已存在");
+        }
+
+        FsCoursePlaySourceConfig config = new FsCoursePlaySourceConfig();
+        BeanUtils.copyProperties(param, config);
+
+        config.setIsDel(0);
+        config.setCreateTime(LocalDateTime.now());
+        config.setUpdateTime(LocalDateTime.now());
+        fsCoursePlaySourceConfigService.save(config);
+        return AjaxResult.success();
+    }
+
+    @PreAuthorize("@ss.hasPermi('course:playSourceConfig:edit')")
+    @Log(title = "点播播放源配置", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@Valid @RequestBody FsCoursePlaySourceConfigEditParam param) {
+        FsCoursePlaySourceConfig config = fsCoursePlaySourceConfigService.getById(param.getId());
+        if (Objects.isNull(config)) {
+            return AjaxResult.error("点播播放源配置不存在");
+        }
+
+        Wrapper<FsCoursePlaySourceConfig> queryWrapper = Wrappers.<FsCoursePlaySourceConfig>lambdaQuery()
+                .eq(FsCoursePlaySourceConfig::getAppid, param.getAppid())
+                .eq(FsCoursePlaySourceConfig::getIsDel, 0)
+                .last("limit 1");
+        FsCoursePlaySourceConfig one = fsCoursePlaySourceConfigService.getOne(queryWrapper);
+        if (Objects.nonNull(one) && !one.getId().equals(config.getId())) {
+            return AjaxResult.error("appid已存在");
+        }
+
+        BeanUtils.copyProperties(param, config);
+        fsCoursePlaySourceConfigService.updateById(config);
+        return AjaxResult.success();
+    }
+
+    @PreAuthorize("@ss.hasPermi('course:playSourceConfig:remove')")
+    @Log(title = "点播播放源配置", businessType = BusinessType.DELETE)
+    @DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids) {
+        Wrapper<FsCoursePlaySourceConfig> updateWrapper = Wrappers.<FsCoursePlaySourceConfig>lambdaUpdate()
+                .set(FsCoursePlaySourceConfig::getIsDel, 1)
+                .in(FsCoursePlaySourceConfig::getId, Arrays.asList(ids));
+        fsCoursePlaySourceConfigService.update(updateWrapper);
+        return AjaxResult.success();
+    }
+}

+ 2 - 8
fs-admin/src/main/java/com/fs/course/controller/FsCourseTrafficLogController.java

@@ -1,6 +1,7 @@
 package com.fs.course.controller;
 
 import java.text.SimpleDateFormat;
+import java.time.format.DateTimeFormatter;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -50,14 +51,7 @@ public class FsCourseTrafficLogController extends BaseController
     public TableDataInfo list(FsCourseTrafficLogParam param)
     {
         startPage();
-        if (param.getTime() != null) {
-            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");
-            String formattedDate = sdf.format(param.getTime());
-            String[] parts = formattedDate.split("-");
-            param.setYear(Integer.parseInt(parts[0]));
-            param.setMonth(Integer.parseInt(parts[1]));
-        }
-        List<FsCourseTrafficLogListVO> list = fsCourseTrafficLogService.selectTrafficByCompany(param);
+        List<FsCourseTrafficLogListVO> list = fsCourseTrafficLogService.selectTrafficNew(param);
         return getDataTable(list);
     }
 

+ 97 - 0
fs-admin/src/main/java/com/fs/fastGpt/FastgptChatArtificialWordsController.java

@@ -0,0 +1,97 @@
+package com.fs.fastGpt;
+
+import com.fs.common.annotation.Log;
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.core.page.TableDataInfo;
+import com.fs.common.enums.BusinessType;
+import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.fastGpt.domain.FastgptChatArtificialWords;
+import com.fs.fastGpt.service.IFastgptChatArtificialWordsService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * 转人工提示词Controller
+ * 
+ * @author fs
+ * @date 2025-05-07
+ */
+@RestController
+@RequestMapping("/fastGpt/fastgptChatArtificialWords")
+public class FastgptChatArtificialWordsController extends BaseController
+{
+    @Autowired
+    private IFastgptChatArtificialWordsService fastgptChatArtificialWordsService;
+
+    /**
+     * 查询转人工提示词列表
+     */
+    @PreAuthorize("@ss.hasPermi('fastGpt:fastgptChatArtificialWords:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(FastgptChatArtificialWords fastgptChatArtificialWords)
+    {
+        startPage();
+        List<FastgptChatArtificialWords> list = fastgptChatArtificialWordsService.selectFastgptChatArtificialWordsList(fastgptChatArtificialWords);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出转人工提示词列表
+     */
+    @PreAuthorize("@ss.hasPermi('fastGpt:fastgptChatArtificialWords:export')")
+    @Log(title = "转人工提示词", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(FastgptChatArtificialWords fastgptChatArtificialWords)
+    {
+        List<FastgptChatArtificialWords> list = fastgptChatArtificialWordsService.selectFastgptChatArtificialWordsList(fastgptChatArtificialWords);
+        ExcelUtil<FastgptChatArtificialWords> util = new ExcelUtil<FastgptChatArtificialWords>(FastgptChatArtificialWords.class);
+        return util.exportExcel(list, "转人工提示词数据");
+    }
+
+    /**
+     * 获取转人工提示词详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('fastGpt:fastgptChatArtificialWords:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id)
+    {
+        return AjaxResult.success(fastgptChatArtificialWordsService.selectFastgptChatArtificialWordsById(id));
+    }
+
+    /**
+     * 新增转人工提示词
+     */
+    @PreAuthorize("@ss.hasPermi('fastGpt:fastgptChatArtificialWords:add')")
+    @Log(title = "转人工提示词", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody FastgptChatArtificialWords fastgptChatArtificialWords)
+    {
+        return toAjax(fastgptChatArtificialWordsService.insertFastgptChatArtificialWords(fastgptChatArtificialWords));
+    }
+
+    /**
+     * 修改转人工提示词
+     */
+    @PreAuthorize("@ss.hasPermi('fastGpt:fastgptChatArtificialWords:edit')")
+    @Log(title = "转人工提示词", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody FastgptChatArtificialWords fastgptChatArtificialWords)
+    {
+        return toAjax(fastgptChatArtificialWordsService.updateFastgptChatArtificialWords(fastgptChatArtificialWords));
+    }
+
+    /**
+     * 删除转人工提示词
+     */
+    @PreAuthorize("@ss.hasPermi('fastGpt:fastgptChatArtificialWords:remove')")
+    @Log(title = "转人工提示词", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids)
+    {
+        return toAjax(fastgptChatArtificialWordsService.deleteFastgptChatArtificialWordsByIds(ids));
+    }
+}

+ 23 - 4
fs-admin/src/main/java/com/fs/his/controller/FsArticleCateController.java

@@ -1,7 +1,9 @@
 package com.fs.his.controller;
 
+import java.util.Collection;
 import java.util.List;
 
+import com.fs.common.core.redis.RedisCache;
 import com.fs.his.vo.OptionsVO;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -24,7 +26,7 @@ import com.fs.common.core.page.TableDataInfo;
 
 /**
  * 文章分类Controller
- * 
+ *
  * @author fs
  * @date 2023-07-04
  */
@@ -34,6 +36,8 @@ public class FsArticleCateController extends BaseController
 {
     @Autowired
     private IFsArticleCateService fsArticleCateService;
+    @Autowired
+    RedisCache redisCache;
 
     /**
      * 查询文章分类列表
@@ -78,7 +82,12 @@ public class FsArticleCateController extends BaseController
     @PostMapping
     public AjaxResult add(@RequestBody FsArticleCate fsArticleCate)
     {
-        return toAjax(fsArticleCateService.insertFsArticleCate(fsArticleCate));
+        int i = fsArticleCateService.insertFsArticleCate(fsArticleCate);
+        Collection<String> keys = redisCache.keys("getArticleCateList*");
+        for (String key : keys) {
+            redisCache.deleteObject(key);
+        }
+        return toAjax(i);
     }
 
     /**
@@ -89,7 +98,12 @@ public class FsArticleCateController extends BaseController
     @PutMapping
     public AjaxResult edit(@RequestBody FsArticleCate fsArticleCate)
     {
-        return toAjax(fsArticleCateService.updateFsArticleCate(fsArticleCate));
+        int i = fsArticleCateService.updateFsArticleCate(fsArticleCate);
+        Collection<String> keys = redisCache.keys("getArticleCateList*");
+        for (String key : keys) {
+            redisCache.deleteObject(key);
+        }
+        return toAjax(i);
     }
 
     /**
@@ -100,7 +114,12 @@ public class FsArticleCateController extends BaseController
 	@DeleteMapping("/{cateIds}")
     public AjaxResult remove(@PathVariable Long[] cateIds)
     {
-        return toAjax(fsArticleCateService.deleteFsArticleCateByCateIds(cateIds));
+        int i = fsArticleCateService.deleteFsArticleCateByCateIds(cateIds);
+        Collection<String> keys = redisCache.keys("getArticleCateList*");
+        for (String key : keys) {
+            redisCache.deleteObject(key);
+        }
+        return toAjax(i);
     }
 
     /**

+ 7 - 2
fs-admin/src/main/java/com/fs/his/controller/FsDoctorArticleController.java

@@ -100,9 +100,14 @@ public class FsDoctorArticleController extends BaseController
     {
         fsDoctorArticleService.updateFsDoctorArticle(fsDoctorArticle);
         Collection<String> keys = redisCache.keys("getDoctorArticleList*");
-        for (String key : keys) {
-            redisCache.deleteObject(key);
+        Collection<String> details = redisCache.keys("getDoctorArticleById::" +fsDoctorArticle.getArticleId());
+        keys.addAll(details);
+        if (!keys.isEmpty()) {
+            for (String key : keys) {
+                redisCache.deleteObject(key);
+            }
         }
+
         return toAjax(1);
     }
 

+ 10 - 8
fs-admin/src/main/java/com/fs/his/controller/FsPackageCateController.java

@@ -7,6 +7,8 @@ import java.util.Map;
 import com.fs.common.core.redis.RedisCache;
 import com.fs.his.param.FsPackageCateUParam;
 import com.fs.his.vo.OptionsVO;
+import org.springframework.cache.annotation.CacheEvict;
+import org.springframework.cache.annotation.Cacheable;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.GetMapping;
@@ -84,10 +86,10 @@ public class FsPackageCateController extends BaseController
     public AjaxResult add(@RequestBody FsPackageCate fsPackageCate)
     {
         fsPackageCateService.insertFsPackageCate(fsPackageCate);
-        Collection<String> keys = redisCache.keys("getPackagCateList*");
-        for (String key : keys) {
-            redisCache.deleteObject(key);
-        }
+//        Collection<String> keys = redisCache.keys("getPackagCateList*");
+//        for (String key : keys) {
+//            redisCache.deleteObject(key);
+//        }
         return toAjax(1);
     }
 
@@ -100,10 +102,10 @@ public class FsPackageCateController extends BaseController
     public AjaxResult edit(@RequestBody FsPackageCate fsPackageCate)
     {
         fsPackageCateService.updateFsPackageCate(fsPackageCate);
-        Collection<String> keys = redisCache.keys("getPackagCateList*");
-        for (String key : keys) {
-            redisCache.deleteObject(key);
-        }
+//        Collection<String> keys = redisCache.keys("getPackagCateList*");
+//        for (String key : keys) {
+//            redisCache.deleteObject(key);
+//        }
         return toAjax(1);
     }
 

+ 20 - 4
fs-admin/src/main/java/com/fs/web/controller/system/SysLoginController.java

@@ -4,7 +4,9 @@ import java.util.List;
 import java.util.Set;
 
 import com.fs.common.core.domain.R;
+import com.fs.common.core.domain.entity.SysRole;
 import com.fs.common.utils.PatternUtils;
+import com.fs.system.service.ISysRoleService;
 import lombok.Synchronized;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.scheduling.annotation.Async;
@@ -24,7 +26,7 @@ import com.fs.system.service.ISysMenuService;
 
 /**
  * 登录验证
- * 
+ *
 
  */
 @RestController
@@ -40,9 +42,12 @@ public class SysLoginController
     @Autowired
     private SysPermissionService permissionService;
 
+    @Autowired
+    private ISysRoleService roleService;
+
     /**
      * 登录方法
-     * 
+     *
      * @param loginBody 登录信息
      * @return 结果
      */
@@ -62,7 +67,7 @@ public class SysLoginController
 
     /**
      * 获取用户信息
-     * 
+     *
      * @return 用户信息
      */
     @GetMapping("getInfo")
@@ -75,14 +80,25 @@ public class SysLoginController
         Set<String> permissions = permissionService.getMenuPermission(user);
         AjaxResult ajax = AjaxResult.success();
         ajax.put("user", user);
+        Integer isAdmin = 0;
+        if (permissions.contains("*:*:*")){
+            isAdmin = 1;
+        }else {
+            List<SysRole> roleList = user.getRoles();
+            if (roleList != null && !roleList.isEmpty()) {
+                Long[] roleIds = roleList.stream().map(SysRole::getRoleId).toArray(Long[]::new);
+                isAdmin = roleService.getIsCheckPhone(roleIds)?1:0;
+            }
+        }
         ajax.put("roles", roles);
         ajax.put("permissions", permissions);
+        ajax.put("isAdmin", isAdmin);
         return ajax;
     }
 
     /**
      * 获取路由信息
-     * 
+     *
      * @return 路由信息
      */
     @GetMapping("getRouters")

+ 23 - 0
fs-common/src/main/java/com/fs/common/utils/CloudHostUtils.java

@@ -0,0 +1,23 @@
+package com.fs.common.utils;
+
+
+import com.fs.common.utils.spring.SpringUtils;
+
+public class CloudHostUtils {
+
+    /**
+     * 是否指定项目名称配置
+     */
+    public static boolean isCloudHostName(String cloudHostName) {
+        String cloudHostNameConfig = SpringUtils.getProperty("cloud_host.company_name");
+        if (StringUtils.isBlank(cloudHostNameConfig)) {
+            return false;
+        }
+
+        if (StringUtils.isBlank(cloudHostName)) {
+            return false;
+        }
+
+        return cloudHostNameConfig.equalsIgnoreCase(cloudHostName);
+    }
+}

+ 10 - 0
fs-common/src/main/java/com/fs/common/utils/spring/SpringUtils.java

@@ -143,4 +143,14 @@ public final class SpringUtils implements BeanFactoryPostProcessor, ApplicationC
         final String[] activeProfiles = getActiveProfiles();
         return StringUtils.isNotEmpty(activeProfiles) ? activeProfiles[0] : null;
     }
+
+    /**
+     * 获取配置文件配置项的值
+     *
+     * @param key 配置项key
+     * @return 属性值
+     */
+    public static String getProperty(String key) {
+        return applicationContext.getEnvironment().getProperty(key);
+    }
 }

+ 1 - 1
fs-company-app/src/main/java/com/fs/app/config/WebMvcConfig.java

@@ -26,4 +26,4 @@ public class WebMvcConfig implements WebMvcConfigurer {
 //    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
 //        argumentResolvers.add(loginUserHandlerMethodArgumentResolver);
 //    }
-}
+}

+ 5 - 1
fs-company-app/src/main/java/com/fs/app/controller/AppBaseController.java

@@ -1,6 +1,7 @@
 package com.fs.app.controller;
 
 
+import cn.hutool.core.util.ObjectUtil;
 import com.fs.app.exception.FSException;
 import com.fs.app.utils.JwtUtils;
 import com.fs.common.core.redis.RedisCache;
@@ -34,7 +35,10 @@ public class AppBaseController {
 	{
 		String headValue =  ServletUtils.getRequest().getHeader("APPToken");
 		Claims claims=jwtUtils.getClaimByToken(headValue);
-		String userId = claims.getSubject().toString();
+		if (ObjectUtil.isEmpty(claims)){
+			throw new FSException("未授权,请先登录!");
+		}
+		String userId = claims.getSubject();
 		return userId;
 	}
 	public Long getCompanyUserId() {

+ 22 - 75
fs-company/src/main/java/com/fs/company/controller/common/Test.java

@@ -4,6 +4,11 @@ import com.alibaba.fastjson.JSON;
 import com.fs.ad.enums.AdUploadType;
 import com.fs.common.annotation.DataSource;
 import com.fs.common.enums.DataSourceType;
+import com.fs.company.service.ICompanyService;
+import com.fs.company.vo.RedPacketMoneyVO;
+import com.fs.course.mapper.FsCourseRedPacketLogMapper;
+import com.fs.erp.service.IErpOrderService;
+import com.fs.his.utils.ConfigUtil;
 import com.fs.qw.vo.AdUploadVo;
 import com.fs.sop.service.IQwSopTempContentService;
 import com.fs.sop.service.IQwSopTempDayService;
@@ -11,88 +16,30 @@ import com.fs.sop.service.IQwSopTempRulesService;
 import com.fs.sop.service.IQwSopTempService;
 import lombok.AllArgsConstructor;
 import org.apache.rocketmq.spring.core.RocketMQTemplate;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.RestController;
 
+import java.util.List;
+
 @RestController
-@AllArgsConstructor
 public class Test {
+    @Autowired
+    private ConfigUtil configUtil;
 
-    private final IQwSopTempService qwSopTempService;
-    private final IQwSopTempRulesService qwSopTempRulesService;
-    private final IQwSopTempDayService qwSopTempDayService;
-    private final IQwSopTempContentService qwSopTempContentService;
-    private final RocketMQTemplate rocketMQTemplate;
+    @Autowired
+    private FsCourseRedPacketLogMapper fsCourseRedPacketLogMapper;
+    @Autowired
+    private ICompanyService companyService;
 
-//    @GetMapping("test")
-//    public void fileDownload(){
-////        List<QwSopTempRules> rulesList = qwSopTempRulesService.listByTempId("3922c166-a539-4a64-a535-d4feafc096c3");
-//        List<QwSopTemp> tempList = qwSopTempService.listTemp().stream().filter(e -> StringUtils.isNotEmpty(e.getSetting())).collect(Collectors.toList());
-//        Map<String, QwSopTemp> tempMap = PubFun.listToMapByGroupObject(tempList, QwSopTemp::getId);
-//        Map<String, List<QwSopTempSetting2>> collect = tempList.stream().collect(Collectors.toMap(QwSopTemp::getId, e -> JSONArray.parseArray(e.getSetting(), QwSopTempSetting2.class)));
-//        collect.forEach((k, rules) -> {
-//            QwSopTemp qwSopTemp = tempMap.get(k);
-//            for (int i = 0; i < rules.size(); i++) {
-//                QwSopTempSetting2 e = rules.get(i);
-//                QwSopTempDay qwSopTempDay = new QwSopTempDay();
-//                qwSopTempDay.setSorts(i);
-//                qwSopTempDay.setName(e.getName());
-//                qwSopTempDay.setDayNum((qwSopTempDay.getSorts() * qwSopTemp.getGap()) + 1);
-//                qwSopTempDay.setTempId(k);
-//                qwSopTemp.getList().add(qwSopTempDay);
-//                for (int i1 = 0; i1 < e.getContent().size(); i1++) {
-//                    QwSopTempRules qwSopTempRules = new QwSopTempRules();
-//                    qwSopTempRules.setTempId(k);
-//                    qwSopTempRules.setName(e.getName());
-//                    qwSopTempRules.setSorts(i1);
-//                    QwSopTempSetting2.Content vo = e.getContent().get(i1);
-//                    qwSopTempRules.setTime(vo.getTime());
-//                    qwSopTempRules.setType(vo.getType());
-//                    qwSopTempRules.setContentType(StringUtils.isNotEmpty(vo.getContentType()) ? Integer.parseInt(vo.getContentType()) : null);
-//                    qwSopTempRules.setCourseType(vo.getCourseType());
-//                    qwSopTempRules.setCourseId(vo.getCourseId());
-//                    qwSopTempRules.setVideoId(vo.getVideoId());
-//                    qwSopTempRules.setAiTouch(vo.getAiTouch());
-//                    qwSopTempDay.getList().add(qwSopTempRules);
-//                    for (int i2 = 0; i2 < vo.getSetting().size(); i2++) {
-//                        QwSopTempSetting2.Content.Setting setting = vo.getSetting().get(i2);
-//                        QwSopTempContent qwSopTempContent = new QwSopTempContent();
-//                        qwSopTempContent.setTempId(k);
-//                        qwSopTempContent.setContentType(StringUtils.isNotEmpty(setting.getContentType()) ? Integer.parseInt(setting.getContentType()) : null);
-//                        qwSopTempContent.setContent(JSON.toJSONString(setting));
-//                        qwSopTempContent.setIsBindUrl(setting.getIsBindUrl());
-//                        qwSopTempContent.setExpiresDays(setting.getExpiresDays());
-//                        qwSopTempRules.getList().add(qwSopTempContent);
-//                    }
-//                }
-//            }
-//        });
-////        System.out.println(1);
-//        tempList.parallelStream().forEach(qwSopTemp -> {
-////            new Thread(() -> {
-//                qwSopTempDayService.saveList(qwSopTemp.getList());
-//                List<QwSopTempRules> ruleList = qwSopTemp.getList().stream().flatMap(e -> e.getList().stream().peek(s -> s.setDayId(e.getId()))).collect(Collectors.toList());
-//                qwSopTempRulesService.saveList(ruleList);
-//                List<QwSopTempContent> contentList = ruleList.stream().flatMap(s -> s.getList().stream().peek(c -> c.setRulesId(s.getId()))).collect(Collectors.toList());
-//                qwSopTempContentService.saveList(contentList);
-////            }).start();
-//        });
-//    }
-//    @GetMapping("test")
-//    @DataSource(DataSourceType.SOP)
-//    public void fileDownload(){
-//        List<QwSopTempContent> contentList = qwSopTempContentService.list(new QueryWrapper<QwSopTempContent>().isNull("day_id"));
-//        List<Long> longs = PubFun.listToNewList(contentList, QwSopTempContent::getRulesId);
-//        List<QwSopTempRules> ruleList = qwSopTempRulesService.list(new QueryWrapper<QwSopTempRules>().in("id", longs));
-//        Map<Long, QwSopTempRules> rulesMap = PubFun.listToMapByGroupObject(ruleList, QwSopTempRules::getId);
-//        contentList.stream().filter(e ->rulesMap.containsKey(e.getRulesId())).forEach(qwSopTempContent -> {
-//            qwSopTempContent.setDayId(rulesMap.get(qwSopTempContent.getRulesId()).getDayId());
-//        });
-//        contentList.forEach(qwSopTempContentService::updateDay);
-//    }
+    @Autowired
+    IErpOrderService erpOrderService;
     @GetMapping("test")
-    @DataSource(DataSourceType.SOP)
-    public void fileDownload(){
-        rocketMQTemplate.syncSend("ad-upload", JSON.toJSONString(AdUploadVo.builder().state("测试").type(AdUploadType.ADD_WX).build()));
+    public void fileDownload() {
+        System.out.println("11111111111111");
+        List<RedPacketMoneyVO> redPacketMoneyVOS = fsCourseRedPacketLogMapper.selectFsCourseRedPacketLogByCompany();
+        for (RedPacketMoneyVO redPacketMoneyVO : redPacketMoneyVOS) {
+            companyService.subtractCompanyMoney(redPacketMoneyVO.getMoney(),redPacketMoneyVO.getCompanyId());
+        }
     }
 }

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

@@ -638,4 +638,11 @@ public class QwExternalContactController extends BaseController
         return getDataTable(qwUserDelLossLogVOS);
     }
 
+    @GetMapping("/delLossStatisticsExport")
+    public AjaxResult delLossStatisticsExport(QwUserDelLossLogParam param){
+        List<QwUserDelLossLogVO> qwUserDelLossLogVOS = qwExternalContactService.selectQwUserDelLossLogList(param);
+        ExcelUtil<QwUserDelLossLogVO> util = new ExcelUtil<QwUserDelLossLogVO>(QwUserDelLossLogVO.class);
+        return util.exportExcel(qwUserDelLossLogVOS, "企微用户删除流失统计");
+    }
+
 }

+ 5 - 0
fs-company/src/main/java/com/fs/company/controller/store/FsUserCouponController.java

@@ -105,6 +105,11 @@ public class FsUserCouponController extends BaseController
     @PostMapping("/sendCoupon")
     public AjaxResult sendCoupon(@RequestBody FsUserCouponSendParam fsUserCoupon)
     {
+        if (fsUserCoupon.getSetSendUserId() == null){
+            LoginUser loginUser = SecurityUtils.getLoginUser();
+            Long userId = loginUser.getUser().getUserId();
+            fsUserCoupon.setSetSendUserId(userId);
+        }
         return toAjax(fsUserCouponService.sendFsUserCoupon(fsUserCoupon));
     }
 

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

@@ -110,7 +110,7 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter
                         "/**/*.js",
                         "/profile/**"
                 ).permitAll()
-
+                .antMatchers("/test").anonymous()
                 .antMatchers("**/callerResult").anonymous()
                 .antMatchers("/qw/getJsapiTicket/**").anonymous()
                 .antMatchers("/msg/**").anonymous()

+ 6 - 2
fs-doctor-app/src/main/java/com/fs/app/controller/DoctorArticleController.java

@@ -103,8 +103,12 @@ public class DoctorArticleController extends  AppBaseController {
 
         if(doctorArticleService.updateFsDoctorArticle(param)>0){
             Collection<String> keys = redisCache.keys("getDoctorArticleList*");
-            for (String key : keys) {
-                redisCache.deleteObject(key);
+            Collection<String> details = redisCache.keys("getDoctorArticleById::" +param.getArticleId());
+            keys.addAll(details);
+            if (!keys.isEmpty()) {
+                for (String key : keys) {
+                    redisCache.deleteObject(key);
+                }
             }
             return R.ok();
         }

+ 7 - 1
fs-doctor-app/src/main/java/com/fs/app/controller/DoctorController.java

@@ -112,6 +112,7 @@ public class DoctorController extends  AppBaseController {
         //获取管理员token
         String userId = userIdMap.get("userId");
         String adminToken = openIMService.getAdminToken();
+
         JSONObject requestBody = new JSONObject();
         // 解析响应
         if (StringUtil.isNotEmpty(adminToken)) {
@@ -128,6 +129,7 @@ public class DoctorController extends  AppBaseController {
                     .body();
             JSONObject jsonObject = new JSONObject(body);
             JSONArray results = jsonObject.getJSONObject("data").getJSONArray("results");
+            System.out.println("查询用户结果:"+results);
             if (results != null && results.length() > 0) {
                 JSONObject resultObj = results.getJSONObject(0);
                 int accountStatus = resultObj.getInt("accountStatus");
@@ -158,10 +160,14 @@ public class DoctorController extends  AppBaseController {
             requestBody = new JSONObject();
             requestBody.put("platformID",5);
             requestBody.put("userID",userId);
-            String body1 = HttpRequest.post(IMConfig.URL+"/api/auth/get_user_token")
+            String body1 = HttpRequest.post(IMConfig.URL+"/auth/get_user_token")
                     .header("operationID", String.valueOf(System.currentTimeMillis()))
                     .header("token", adminToken)
                     .body(requestBody.toString()).execute().body();
+            System.out.println("operationID"+System.currentTimeMillis());
+            System.out.println("adimtoken"+adminToken);
+            System.out.println("IPad地址"+IMConfig.URL+"/api/auth/get_user_token");
+            System.out.println("json接送内容:"+body1);
             JSONObject userJson = new JSONObject(body1);
             JSONObject userData = userJson.getJSONObject("data");
             String userToken = userData.getString("token");

+ 1 - 5
fs-doctor-app/src/main/java/com/fs/app/controller/InquiryOrderController.java

@@ -96,11 +96,7 @@ public class InquiryOrderController extends  AppBaseController {
         FsDoctor doctor=doctorService.selectFsDoctorByDoctorId(Long.parseLong(getDoctorId()));
         PageHelper.startPage(param.getPageNum(), param.getPageSize());
 
-        if (Objects.nonNull(param.getUserId())) {
-            param.setDoctorId(null);
-        } else if (Objects.nonNull(param.getDoctorId())) {
-            param.setDoctorId(Long.parseLong(getDoctorId()));
-        }
+        param.setDoctorId(Long.parseLong(getDoctorId()));
 
         param.setIsAccept(doctor.getIsAccept());
         param.setIsSelf(doctor.getIsSelf());

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

@@ -10,4 +10,4 @@ spring:
 #    active: druid-yzt
 #    active: druid-hdt
 #    active: druid-sxjz
-    active: druid-sft
+    active: dev

+ 62 - 15
fs-service/src/main/java/com/fs/core/config/WxMaConfiguration.java

@@ -8,7 +8,12 @@ import cn.binarywang.wx.miniapp.config.impl.WxMaDefaultConfigImpl;
 import cn.binarywang.wx.miniapp.message.WxMaMessageHandler;
 import cn.binarywang.wx.miniapp.message.WxMaMessageRouter;
 import com.alibaba.fastjson.JSON;
+import com.baomidou.mybatisplus.core.conditions.Wrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.fs.common.utils.spring.SpringUtils;
 import com.fs.course.config.CourseMaConfig;
+import com.fs.course.domain.FsCoursePlaySourceConfig;
+import com.fs.course.mapper.FsCoursePlaySourceConfigMapper;
 import com.fs.system.domain.SysConfig;
 import com.fs.system.mapper.SysConfigMapper;
 import com.google.common.collect.Lists;
@@ -18,6 +23,7 @@ import lombok.extern.slf4j.Slf4j;
 import me.chanjar.weixin.common.bean.result.WxMediaUploadResult;
 import me.chanjar.weixin.common.error.WxErrorException;
 import me.chanjar.weixin.common.error.WxRuntimeException;
+import org.jetbrains.annotations.NotNull;
 import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.annotation.ComponentScan;
@@ -41,7 +47,7 @@ public class WxMaConfiguration {
     private static Map<String, WxMaService> maServices;
 
     @Autowired
-    public WxMaConfiguration(SysConfigMapper sysConfigMapper) {
+    public WxMaConfiguration(SysConfigMapper sysConfigMapper, FsCoursePlaySourceConfigMapper configMapper) {
         SysConfig sysConfig = sysConfigMapper.selectConfigByConfigKey("his.config");
         String configValue = sysConfig.getConfigValue();
         //下单小程序加载
@@ -73,18 +79,69 @@ public class WxMaConfiguration {
                 }
             }
         }
+
+        //  加载点播配置表配置
+        Wrapper<FsCoursePlaySourceConfig> queryWrapper = Wrappers.<FsCoursePlaySourceConfig>lambdaQuery().eq(FsCoursePlaySourceConfig::getIsDel, 0);
+        for (FsCoursePlaySourceConfig playConfig : configMapper.selectList(queryWrapper)) {
+            boolean isExist = c.stream().anyMatch(item -> item.getAppid().equals(playConfig.getAppid()));
+            if (!isExist){
+                WxMaConfig.Config wxMaConfig = new WxMaConfig.Config();
+                BeanUtils.copyProperties(playConfig, wxMaConfig);
+                c.add(wxMaConfig);
+            }
+        }
+
         wx.setConfigs(c);
         this.properties = wx;
         log.info("配置加载完毕! 配置文件: {}",JSON.toJSONString(this.properties));
     }
 
     public static WxMaService getMaService(String appid) {
+        // 从缓存获取
         WxMaService wxService = maServices.get(appid);
-        if (wxService == null) {
-            throw new IllegalArgumentException(String.format("未找到对应appid=[%s]的配置,请核实!", appid));
+        if (wxService != null) {
+            return wxService;
         }
 
-        return wxService;
+        // 缓存未命中,查询数据库
+        synchronized (WxMaConfiguration.class) {
+            // 双重检查
+            wxService = maServices.get(appid);
+            if (wxService != null) {
+                return wxService;
+            }
+
+            // 查询数据库
+            FsCoursePlaySourceConfigMapper configMapper = SpringUtils.getBean(FsCoursePlaySourceConfigMapper.class);
+            Wrapper<FsCoursePlaySourceConfig> queryWrapper = Wrappers.<FsCoursePlaySourceConfig>lambdaQuery()
+                    .eq(FsCoursePlaySourceConfig::getAppid, appid)
+                    .eq(FsCoursePlaySourceConfig::getIsDel, 0);
+            FsCoursePlaySourceConfig config = configMapper.selectOne(queryWrapper);
+            if (config == null) {
+                throw new IllegalArgumentException(String.format("未找到对应appid=[%s]的配置,请核实!", appid));
+            }
+
+            WxMaService service = getWxMaService(config.getAppid(), config.getSecret(), config.getToken(), config.getAesKey(), config.getMsgDataFormat());
+            maServices.put(appid, service);
+            log.info("Initialized WxMaService for appid: {}", appid);
+            return service;
+        }
+    }
+
+    /**
+     * 初始化WxMaService
+     */
+    private static WxMaService getWxMaService(String appid, String secret, String token, String aesKey, String msgDataFormat) {
+        WxMaDefaultConfigImpl maConfig = new WxMaDefaultConfigImpl();
+        maConfig.setAppid(appid);
+        maConfig.setSecret(secret);
+        maConfig.setToken(token);
+        maConfig.setAesKey(aesKey);
+        maConfig.setMsgDataFormat(msgDataFormat);
+
+        WxMaService service = new WxMaServiceImpl();
+        service.setWxMaConfig(maConfig);
+        return service;
     }
 
     public static WxMaMessageRouter getRouter(String appid) {
@@ -100,17 +157,7 @@ public class WxMaConfiguration {
 
         maServices = configs.stream()
             .map(a -> {
-                WxMaDefaultConfigImpl config = new WxMaDefaultConfigImpl();
-//                WxMaDefaultConfigImpl config = new WxMaRedisConfigImpl(new JedisPool());
-                // 使用上面的配置时,需要同时引入jedis-lock的依赖,否则会报类无法找到的异常
-                config.setAppid(a.getAppid());
-                config.setSecret(a.getSecret());
-                config.setToken(a.getToken());
-                config.setAesKey(a.getAesKey());
-                config.setMsgDataFormat(a.getMsgDataFormat());
-
-                WxMaService service = new WxMaServiceImpl();
-                service.setWxMaConfig(config);
+                WxMaService service = getWxMaService(a.getAppid(), a.getSecret(), a.getToken(), a.getAesKey(), a.getMsgDataFormat());
                 routers.put(a.getAppid(), this.newRouter(service));
                 return service;
             }).collect(Collectors.toMap(s -> s.getWxMaConfig().getAppid(), a -> a));

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

@@ -0,0 +1,79 @@
+package com.fs.course.domain;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+@Data
+@TableName("fs_course_play_source_config")
+public class FsCoursePlaySourceConfig {
+
+    /**
+     * 主键ID
+     */
+    @TableId(type = IdType.AUTO)
+    private Long id;
+
+    /**
+     * 小程序/公众号名称
+     */
+    private String name;
+
+    /**
+     * 小程序/公众号appid
+     */
+    private String appid;
+
+    /**
+     * 小程序/公众号secret
+     */
+    private String secret;
+
+    /**
+     * 小程序/公众号icon图标
+     */
+    private String img;
+
+    /**
+     * 小程序/公众号原始id
+     */
+    private String originalId;
+
+    /**
+     * token
+     */
+    private String token;
+
+    /**
+     * aesKey
+     */
+    private String aesKey;
+
+    /**
+     * msgDataFormat
+     */
+    private String msgDataFormat;
+
+    /**
+     * 类型 1小程序 2公众号
+     */
+    private Integer type;
+
+    /**
+     * 是否删除 0正常 1删除
+     */
+    private Integer isDel;
+
+    /**
+     * 创建时间
+     */
+    private LocalDateTime createTime;
+
+    /**
+     * 修改时间
+     */
+    private LocalDateTime updateTime;
+}

+ 17 - 0
fs-service/src/main/java/com/fs/course/mapper/FsCoursePlaySourceConfigMapper.java

@@ -0,0 +1,17 @@
+package com.fs.course.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.fs.course.domain.FsCoursePlaySourceConfig;
+import com.fs.course.vo.FsCoursePlaySourceConfigVO;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+import java.util.Map;
+
+public interface FsCoursePlaySourceConfigMapper extends BaseMapper<FsCoursePlaySourceConfig> {
+
+    /**
+     * 查询点播配置列表
+     */
+    List<FsCoursePlaySourceConfigVO> selectCoursePlaySourceConfigVOListByMap(@Param("params") Map<String, Object> params);
+}

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

@@ -70,6 +70,7 @@ public interface FsUserCourseVideoRedPackageMapper
             "VALUES (#{companyId}, #{videoId}, #{redPacketMoney}) " +
             "ON DUPLICATE KEY UPDATE red_packet_money = VALUES(red_packet_money);")
     void insertOrUpdateFsUserCourseVideoRedPackage(FsUserCourseVideoParam fsUserCourseVideo);
+
     @Select("select * from fs_user_course_video_red_package where video_id =#{videoId} and company_id = #{companyId} and period_id = #{periodId}")
     FsUserCourseVideoRedPackage selectRedPacketByCompanyId(@Param("videoId") Long videoId,@Param("companyId") Long companyId, @Param("periodId") Long periodId);
 

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

@@ -0,0 +1,45 @@
+package com.fs.course.param;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+
+@Data
+public class FsCoursePlaySourceConfigCreateParam {
+
+    @NotBlank(message = "名称不能为空")
+    @ApiModelProperty("小程序/公众号名称")
+    private String name;
+
+    @NotBlank(message = "appid不能为空")
+    @ApiModelProperty("小程序/公众号appid")
+    private String appid;
+
+    @NotBlank(message = "secret不能为空")
+    @ApiModelProperty("小程序/公众号secret")
+    private String secret;
+
+    @ApiModelProperty("小程序/公众号icon图标")
+    private String img;
+
+    @ApiModelProperty("小程序/公众号原始id")
+    private String originalId;
+
+    @NotBlank(message = "token不能为空")
+    @ApiModelProperty("token")
+    private String token;
+
+    @NotBlank(message = "aesKey不能为空")
+    @ApiModelProperty("aesKey")
+    private String aesKey;
+
+    @NotBlank(message = "msgDataFormat不能为空")
+    @ApiModelProperty("msgDataFormat")
+    private String msgDataFormat;
+
+    @NotNull(message = "类型不能为空")
+    @ApiModelProperty("类型 1小程序 2公众号")
+    private Integer type;
+}

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

@@ -0,0 +1,42 @@
+package com.fs.course.param;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+
+@Data
+public class FsCoursePlaySourceConfigEditParam {
+
+    @NotNull(message = "主键ID不能为空")
+    @ApiModelProperty("主键ID")
+    private Long id;
+
+    @ApiModelProperty("小程序/公众号名称")
+    private String name;
+
+    @ApiModelProperty("小程序/公众号appid")
+    private String appid;
+
+    @ApiModelProperty("小程序/公众号secret")
+    private String secret;
+
+    @ApiModelProperty("小程序/公众号icon图标")
+    private String img;
+
+    @ApiModelProperty("小程序/公众号原始id")
+    private String originalId;
+
+    @ApiModelProperty("token")
+    private String token;
+
+    @ApiModelProperty("aesKey")
+    private String aesKey;
+
+    @ApiModelProperty("msgDataFormat")
+    private String msgDataFormat;
+
+    @ApiModelProperty("类型 1小程序 2公众号")
+    private Integer type;
+}

+ 3 - 0
fs-service/src/main/java/com/fs/course/param/FsCourseWatchLogListParam.java

@@ -75,4 +75,7 @@ public class FsCourseWatchLogListParam implements Serializable {
      * 部门类型 00 管理员 01 员工
      */
     private String userType;
+
+    //是否是会员
+    private Integer isVip;
 }

+ 3 - 0
fs-service/src/main/java/com/fs/course/param/PeriodCountParam.java

@@ -30,5 +30,8 @@ public class PeriodCountParam implements Serializable {
 
     private LocalDate maxDate;
 
+    @ApiModelProperty(value = "公司ID")
+    private Long companyId;
+
 }
 

+ 16 - 0
fs-service/src/main/java/com/fs/course/service/IFsCoursePlaySourceConfigService.java

@@ -0,0 +1,16 @@
+package com.fs.course.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.fs.course.domain.FsCoursePlaySourceConfig;
+import com.fs.course.vo.FsCoursePlaySourceConfigVO;
+
+import java.util.List;
+import java.util.Map;
+
+public interface IFsCoursePlaySourceConfigService extends IService<FsCoursePlaySourceConfig> {
+
+    /**
+     * 查询点播配置列表
+     */
+    List<FsCoursePlaySourceConfigVO> selectCoursePlaySourceConfigVOListByMap(Map<String, Object> params);
+}

+ 27 - 0
fs-service/src/main/java/com/fs/course/service/impl/FsCoursePlaySourceConfigServiceImpl.java

@@ -0,0 +1,27 @@
+package com.fs.course.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.fs.course.domain.FsCoursePlaySourceConfig;
+import com.fs.course.mapper.FsCoursePlaySourceConfigMapper;
+import com.fs.course.service.IFsCoursePlaySourceConfigService;
+import com.fs.course.vo.FsCoursePlaySourceConfigVO;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+@Service
+@Slf4j
+public class FsCoursePlaySourceConfigServiceImpl extends ServiceImpl<FsCoursePlaySourceConfigMapper, FsCoursePlaySourceConfig>
+        implements IFsCoursePlaySourceConfigService {
+
+    /**
+     * 查询点播配置列表
+     */
+    @Override
+    public List<FsCoursePlaySourceConfigVO> selectCoursePlaySourceConfigVOListByMap(Map<String, Object> params) {
+        return baseMapper.selectCoursePlaySourceConfigVOListByMap(params);
+    }
+}

+ 28 - 26
fs-service/src/main/java/com/fs/course/service/impl/FsCourseQuestionBankServiceImpl.java

@@ -187,35 +187,37 @@ public class FsCourseQuestionBankServiceImpl implements IFsCourseQuestionBankSer
         int remainCount = config.getAnswerErrorCount()-errorCount-1;
 
         // 一次性获取所有问题的正确答案
-        Map<Long, FsCourseQuestionBank> correctAnswersMap = fsCourseQuestionBankMapper.selectFsCourseQuestionBankByIds(
-                param.getQuestions().stream().map(FsCourseQuestionBank::getId).collect(Collectors.toList())
-        ).stream().collect(Collectors.toMap(FsCourseQuestionBank::getId, question -> question));
-
-        for (FsCourseQuestionBank questionBank : param.getQuestions()) {
-            FsCourseQuestionBank correctAnswer = correctAnswersMap.get(questionBank.getId());
-            if (correctAnswer.getType() == 1) {
-                if (questionBank.getAnswer().equals(correctAnswer.getAnswer())) {
-                    thisRightCount++;
-                } else {
-                    correctAnswer.setAnswer(null);
-                    incorrectQuestions.add(correctAnswer);
-                }
-            } else if (correctAnswer.getType() == 2) {
-                String[] userAnswers = convertStringToArray(questionBank.getAnswer());
-                String[] correctAnswers = convertStringToArray(correctAnswer.getAnswer());
+        List<FsCourseQuestionBank> questions = param.getQuestions();
+        if (questions != null && !questions.isEmpty()) {
+            Map<Long, FsCourseQuestionBank> correctAnswersMap = fsCourseQuestionBankMapper.selectFsCourseQuestionBankByIds(
+                    questions.stream().map(FsCourseQuestionBank::getId).collect(Collectors.toList())
+            ).stream().collect(Collectors.toMap(FsCourseQuestionBank::getId, question -> question));
+
+            for (FsCourseQuestionBank questionBank : questions) {
+                FsCourseQuestionBank correctAnswer = correctAnswersMap.get(questionBank.getId());
+                if (correctAnswer.getType() == 1) {
+                    if (questionBank.getAnswer().equals(correctAnswer.getAnswer())) {
+                        thisRightCount++;
+                    } else {
+                        correctAnswer.setAnswer(null);
+                        incorrectQuestions.add(correctAnswer);
+                    }
+                } else if (correctAnswer.getType() == 2) {
+                    String[] userAnswers = convertStringToArray(questionBank.getAnswer());
+                    String[] correctAnswers = convertStringToArray(correctAnswer.getAnswer());
 
-                Arrays.sort(userAnswers);
-                Arrays.sort(correctAnswers);
+                    Arrays.sort(userAnswers);
+                    Arrays.sort(correctAnswers);
 
-                if (Arrays.equals(userAnswers, correctAnswers)) {
-                    thisRightCount++;
-                } else {
-                    correctAnswer.setAnswer(null);
-                    incorrectQuestions.add(correctAnswer);
+                    if (Arrays.equals(userAnswers, correctAnswers)) {
+                        thisRightCount++;
+                    } else {
+                        correctAnswer.setAnswer(null);
+                        incorrectQuestions.add(correctAnswer);
+                    }
                 }
             }
         }
-
         FsCourseAnswerLogs logs = new FsCourseAnswerLogs();
         logs.setWatchLogId(logId);
         logs.setUserId(param.getUserId());
@@ -224,11 +226,11 @@ public class FsCourseQuestionBankServiceImpl implements IFsCourseQuestionBankSer
         logs.setCompanyId(param.getCompanyId());
         logs.setCompanyUserId(param.getCompanyUserId());
         logs.setQwUserId(param.getQwUserId() != null ? param.getQwUserId() : null );
-        logs.setQuestionJson(JSONObject.toJSONString(param.getQuestions()));
+        logs.setQuestionJson(JSONObject.toJSONString(questions));
         logs.setCreateTime(new Date());
         logs.setPeriodId(param.getPeriodId());
 
-        if (thisRightCount == param.getQuestions().size()) {
+        if (thisRightCount == questions.size()) {
             logs.setIsRight(1);
             courseAnswerLogsMapper.insertFsCourseAnswerLogs(logs);
             return R.ok("答题成功");

+ 32 - 5
fs-service/src/main/java/com/fs/course/service/impl/FsCourseWatchLogServiceImpl.java

@@ -366,9 +366,18 @@ public class FsCourseWatchLogServiceImpl extends ServiceImpl<FsCourseWatchLogMap
         for (String key : keys) {
             //取key中数据
             String[] parts = key.split(":");
-            Long userId = Long.parseLong(parts[3]);
-            Long videoId = Long.parseLong(parts[4]);
-            Long companyUserId = Long.parseLong(parts[5]);
+            Long userId=null;
+            Long videoId=null;
+            Long companyUserId=null;
+            try {
+                userId = Long.parseLong(parts[3]);
+                videoId = Long.parseLong(parts[4]);
+                companyUserId = Long.parseLong(parts[5]);
+
+            }catch (Exception e){
+                log.error("key中id为null:{}", key);
+                continue;
+            }
             String durationStr = redisCache.getCacheObject(key);
             if(durationStr==null){
                 log.error("key中数据为null:{}",key);
@@ -405,7 +414,16 @@ public class FsCourseWatchLogServiceImpl extends ServiceImpl<FsCourseWatchLogMap
     public Long getFsUserVideoDuration(Long videoId){
         //将视频时长也存到redis
         String videoRedisKey = "h5wxuser:video:duration:" + videoId;
-        Long videoDuration = redisCache.getCacheObject(videoRedisKey);
+        Long videoDuration=0L;
+        try {
+            videoDuration = redisCache.getCacheObject(videoRedisKey);
+        }catch (Exception e){
+            String string = redisCache.getCacheObject(videoRedisKey);
+            videoDuration=Long.parseLong(string);
+            log.error("key中id为S:{}", videoDuration);
+        }
+
+        
         if (videoDuration==null){
             FsUserCourseVideo video = courseVideoMapper.selectFsUserCourseVideoByVideoId(videoId);
             videoDuration=video.getDuration();
@@ -948,7 +966,16 @@ public class FsCourseWatchLogServiceImpl extends ServiceImpl<FsCourseWatchLogMap
     public Long getVideoDuration(Long videoId){
         //将视频时长也存到redis
         String videoRedisKey = "h5user:video:duration:" + videoId;
-        Long videoDuration = redisCache.getCacheObject(videoRedisKey);
+        Long videoDuration=0L;
+        try {
+            videoDuration = redisCache.getCacheObject(videoRedisKey);
+        }catch (Exception e){
+            String string = redisCache.getCacheObject(videoRedisKey);
+            videoDuration=Long.parseLong(string);
+            log.error("key中id为S:{}", videoDuration);
+        }
+
+
         if (videoDuration==null){
             FsUserCourseVideo video = courseVideoMapper.selectFsUserCourseVideoByVideoId(videoId);
             videoDuration=video.getDuration();

+ 26 - 12
fs-service/src/main/java/com/fs/course/service/impl/FsUserCourseOrderServiceImpl.java

@@ -6,6 +6,8 @@ import java.util.*;
 import cn.hutool.core.util.IdUtil;
 import cn.hutool.json.JSONUtil;
 import com.alibaba.fastjson.JSON;
+import com.baomidou.mybatisplus.core.conditions.Wrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.fs.common.core.domain.R;
 import com.fs.common.exception.CustomException;
 import com.fs.common.utils.DateUtils;
@@ -24,10 +26,7 @@ import com.fs.his.domain.*;
 import com.fs.his.dto.PayConfigDTO;
 import com.fs.his.enums.FsPackageOrderStatusEnum;
 import com.fs.his.enums.FsUserIntegralLogTypeEnum;
-import com.fs.his.mapper.FsStorePaymentErrorMapper;
-import com.fs.his.mapper.FsStorePaymentMapper;
-import com.fs.his.mapper.FsUserIntegralLogsMapper;
-import com.fs.his.mapper.FsUserMapper;
+import com.fs.his.mapper.*;
 import com.fs.his.param.FsPackageOrderDoPayParam;
 import com.fs.his.param.FsUserAddIntegralTemplateParam;
 import com.fs.his.service.IFsCouponService;
@@ -128,6 +127,8 @@ public class FsUserCourseOrderServiceImpl implements IFsUserCourseOrderService
     private TzBankService tzBankService;
     @Autowired
     private IFsUserIntegralLogsService userIntegralLogsService;
+    @Autowired
+    private FsUserWxMapper fsUserWxMapper;
 
 
 
@@ -372,13 +373,26 @@ public class FsUserCourseOrderServiceImpl implements IFsUserCourseOrderService
             return R.error("非法操作");
         }
         FsUser user=fsUserMapper.selectFsUserByUserId(param.getUserId());
-        if(user!=null&& StringUtils.isNotEmpty(user.getMaOpenId())) {
+
+        String json = configService.selectConfigByKey("his.pay");
+        PayConfigDTO payConfigDTO = JSONUtil.toBean(json, PayConfigDTO.class);
+
+        String openId = Objects.isNull(user) ? "" : user.getMaOpenId();
+        if (StringUtils.isBlank(openId)){
+            Wrapper<FsUserWx> queryWrapper = Wrappers.<FsUserWx>lambdaQuery()
+                    .eq(FsUserWx::getFsUserId, param.getUserId())
+                    .eq(FsUserWx::getAppId, payConfigDTO.getAppId());
+            FsUserWx fsUserWx = fsUserWxMapper.selectOne(queryWrapper);
+            if (Objects.nonNull(fsUserWx)){
+                openId = fsUserWx.getOpenId();
+            }
+        }
+
+        if(user!=null&& StringUtils.isNotEmpty(openId)) {
             if (order.getPayMoney().compareTo(new BigDecimal(0)) == 0) {
                 this.payConfirm(order.getOrderCode(), "", "", "", 2);
                 return R.ok().put("isPay", 1);
             } else {
-                String json = configService.selectConfigByKey("his.pay");
-                PayConfigDTO payConfigDTO = JSONUtil.toBean(json, PayConfigDTO.class);
                 String payCode =  OrderCodeUtils.getOrderSn();
                 if(StringUtils.isEmpty(payCode)){
                     return R.error("订单生成失败,请重试");
@@ -393,7 +407,7 @@ public class FsUserCourseOrderServiceImpl implements IFsUserCourseOrderService
                 storePayment.setPayTypeCode("weixin");
                 storePayment.setBusinessType(4);
                 storePayment.setRemark("课程订单支付");
-                storePayment.setOpenId(user.getMaOpenId());
+                storePayment.setOpenId(openId);
                 storePayment.setUserId(user.getUserId());
                 storePayment.setBusinessId(order.getOrderId().toString());
                 if (storePaymentService.insertFsStorePayment(storePayment) > 0) {
@@ -411,7 +425,7 @@ public class FsUserCourseOrderServiceImpl implements IFsUserCourseOrderService
                         payConfig.setNotifyUrl(wxPayProperties.getNotifyUrl());
                         wxPayService.setConfig(payConfig);
                         WxPayUnifiedOrderRequest orderRequest = new WxPayUnifiedOrderRequest();
-                        orderRequest.setOpenid(user.getMaOpenId());//公众号支付提供用户openid
+                        orderRequest.setOpenid(openId);//公众号支付提供用户openid
                         orderRequest.setBody("课程订单支付");
                         orderRequest.setOutTradeNo("course-" + storePayment.getPayCode());
                         orderRequest.setTotalFee(WxPayUnifiedOrderRequest.yuanToFen(storePayment.getPayMoney().toString()));//测试
@@ -433,7 +447,7 @@ public class FsUserCourseOrderServiceImpl implements IFsUserCourseOrderService
                         p.setLowOrderId("course-" + storePayment.getPayCode());
                         p.setBody("课程订单支付");
                         p.setIsMinipg("1");
-                        p.setOpenId(user.getMaOpenId());
+                        p.setOpenId(openId);
                         p.setAttach("");
                         p.setStoreid("0");
                         CreateWxOrderResult wxOrder = payService.createWxOrder(p);
@@ -457,7 +471,7 @@ public class FsUserCourseOrderServiceImpl implements IFsUserCourseOrderService
                         }
                         o.setPayerName("微信用户" + phone);
                         o.setGoodsInfo("课程订单支付"); // 订单信息
-                        o.setOpenId(user.getMaOpenId());
+                        o.setOpenId(openId);
                         o.setOrderType(4);
                         o.setOrderId(order.getOrderId().toString());
                         TzBankResult<PayCreateOrderResult> result = tzBankService.createOrder(o);
@@ -469,7 +483,7 @@ public class FsUserCourseOrderServiceImpl implements IFsUserCourseOrderService
                     } else if (payConfigDTO.getType().equals("hf")) {
                         HuiFuCreateOrder o = new HuiFuCreateOrder();
                         o.setTradeType("T_MINIAPP");
-                        o.setOpenid(user.getMaOpenId());
+                        o.setOpenid(openId);
                         o.setReqSeqId("course-" + storePayment.getPayCode());
                         o.setTransAmt(storePayment.getPayMoney().toString());
                         o.setGoodsDesc("课程订单支付");

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

@@ -245,6 +245,7 @@ public class FsUserCoursePeriodDaysServiceImpl extends ServiceImpl<FsUserCourseP
         CourseAnalysisParam courseAnalysisParam = new CourseAnalysisParam();
         courseAnalysisParam.setPeriodId(param.getPeriodId());
         courseAnalysisParam.setVideoIdList(param.getVideoIdList());
+        courseAnalysisParam.setCompanyId(param.getCompanyId());
         List<FsCourseAnalysisCountVO> courseCountList = fsUserMapper.courseAnalysisWatchLog(courseAnalysisParam);
         List<FsCourseAnalysisCountVO> redPacketCountList = fsUserMapper.courseAnalysisRedPacketCount(courseAnalysisParam);
         List<FsCourseAnalysisCountVO> answerCountList = fsUserMapper.courseAnalysisAnswerCount(courseAnalysisParam);

+ 16 - 3
fs-service/src/main/java/com/fs/course/service/impl/FsUserCourseVideoServiceImpl.java

@@ -926,7 +926,6 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
     }
 
     @Override
-    @Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class)
     public R sendRewardByFsUser(FsCourseSendRewardUParam param) {
         FsUser user = fsUserMapper.selectFsUserByUserId(param.getUserId());
         if (user == null){
@@ -1200,18 +1199,23 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
                 try {
                     handleFsUserWx(user,param.getAppId());
                 }catch (Exception e){
-                    logger.error("zyp \n 【更新或插入用户与小程序的绑定关系失败】:{}", user.getUserId());
+                    logger.error("zyp \n 【更新或插入用户与小程序的绑定关系失败】:{}", user.getUserId(),e);
                 }
 
             }else {
                 packetParam.setOpenId(fsUserWx.getOpenId());
             }
         }
+        //判断服务号配置是否存在
+        if (StringUtils.isNotEmpty(config.getMpAppId())){
+            packetParam.setMpAppId(config.getMpAppId());
+        }
         packetParam.setAmount(amount);
         packetParam.setSource(param.getSource());
         packetParam.setRedPacketMode(config.getRedPacketMode());
         packetParam.setCompanyId(param.getCompanyId());
         packetParam.setAppId(param.getAppId());
+        packetParam.setUser(user);
 
         System.out.println("红包金额"+amount);
         System.out.println("红包商户号"+packetParam);
@@ -1805,7 +1809,16 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
 
         //将视频时长也存到redis
         String videoRedisKey = "h5wxuser:video:duration:" + param.getVideoId();
-        Long videoDuration = redisCache.getCacheObject(videoRedisKey);
+
+        Long videoDuration=0L;
+        try {
+            videoDuration = redisCache.getCacheObject(videoRedisKey);
+        }catch (Exception e){
+            String string = redisCache.getCacheObject(videoRedisKey);
+            videoDuration=Long.parseLong(string);
+            log.error("key中id为String:{}", videoDuration);
+        }
+
         if (videoDuration == null) {
             redisCache.setCacheObject(videoRedisKey, courseVideoDetails != null ? courseVideoDetails.getDuration() != null ? courseVideoDetails.getDuration() : 0 : 0);
         }

+ 28 - 12
fs-service/src/main/java/com/fs/course/service/impl/FsUserVipOrderServiceImpl.java

@@ -6,9 +6,12 @@ import java.time.ZoneId;
 import java.util.Arrays;
 import java.util.Date;
 import java.util.List;
+import java.util.Objects;
 
 import cn.hutool.core.util.IdUtil;
 import cn.hutool.json.JSONUtil;
+import com.baomidou.mybatisplus.core.conditions.Wrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.fs.common.core.domain.R;
 import com.fs.common.exception.CustomException;
 import com.fs.common.utils.DateUtils;
@@ -24,14 +27,12 @@ import com.fs.course.param.FsUserVipOrderCreateUParam;
 import com.fs.course.param.FsUserVipOrderParam;
 import com.fs.course.param.FsUserVipOrderPayUParam;
 import com.fs.course.vo.FsUserVipOrderListPVO;
-import com.fs.his.domain.FsPayConfig;
-import com.fs.his.domain.FsStorePayment;
-import com.fs.his.domain.FsStorePaymentError;
-import com.fs.his.domain.FsUser;
+import com.fs.his.domain.*;
 import com.fs.his.dto.PayConfigDTO;
 import com.fs.his.mapper.FsStorePaymentErrorMapper;
 import com.fs.his.mapper.FsStorePaymentMapper;
 import com.fs.his.mapper.FsUserMapper;
+import com.fs.his.mapper.FsUserWxMapper;
 import com.fs.his.service.IFsStorePaymentService;
 import com.fs.huifuPay.domain.HuiFuCreateOrder;
 import com.fs.huifuPay.domain.HuifuCreateOrderResult;
@@ -111,6 +112,8 @@ public class FsUserVipOrderServiceImpl implements IFsUserVipOrderService
 
     @Autowired
     private IPayService payService;
+    @Autowired
+    private FsUserWxMapper fsUserWxMapper;
 
 
     /**
@@ -229,13 +232,26 @@ public class FsUserVipOrderServiceImpl implements IFsUserVipOrderService
             return R.error("非法操作");
         }
         FsUser user = userMapper.selectFsUserByUserId(param.getUserId());
-        if(user!=null&& StringUtils.isNotEmpty(user.getMaOpenId())) {
+
+        String json = configService.selectConfigByKey("his.pay");
+        PayConfigDTO payConfigDTO = JSONUtil.toBean(json, PayConfigDTO.class);
+
+        String openId = Objects.isNull(user) ? "" : user.getMaOpenId();
+        if (StringUtils.isBlank(openId)){
+            Wrapper<FsUserWx> queryWrapper = Wrappers.<FsUserWx>lambdaQuery()
+                    .eq(FsUserWx::getFsUserId, param.getUserId())
+                    .eq(FsUserWx::getAppId, payConfigDTO.getAppId());
+            FsUserWx fsUserWx = fsUserWxMapper.selectOne(queryWrapper);
+            if (Objects.nonNull(fsUserWx)){
+                openId = fsUserWx.getOpenId();
+            }
+        }
+
+        if(user!=null&& StringUtils.isNotEmpty(openId)) {
             if (order.getPayMoney().compareTo(new BigDecimal(0)) == 0) {
                 this.payConfirm(order.getOrderCode(), "", "", "", 2);
                 return R.ok().put("isPay", 1);
             } else {
-                String json = configService.selectConfigByKey("his.pay");
-                PayConfigDTO payConfigDTO = JSONUtil.toBean(json, PayConfigDTO.class);
                 String payCode =  OrderCodeUtils.getOrderSn();
                 if(StringUtils.isEmpty(payCode)){
                     return R.error("订单生成失败,请重试");
@@ -250,7 +266,7 @@ public class FsUserVipOrderServiceImpl implements IFsUserVipOrderService
                 storePayment.setPayTypeCode("weixin");
                 storePayment.setBusinessType(5);
                 storePayment.setRemark("会员开通订单支付");
-                storePayment.setOpenId(user.getMaOpenId());
+                storePayment.setOpenId(openId);
                 storePayment.setUserId(user.getUserId());
                 storePayment.setBusinessId(order.getOrderId().toString());
                 if (storePaymentService.insertFsStorePayment(storePayment) > 0) {
@@ -268,7 +284,7 @@ public class FsUserVipOrderServiceImpl implements IFsUserVipOrderService
                         payConfig.setNotifyUrl(wxPayProperties.getNotifyUrl());
                         wxPayService.setConfig(payConfig);
                         WxPayUnifiedOrderRequest orderRequest = new WxPayUnifiedOrderRequest();
-                        orderRequest.setOpenid(user.getMaOpenId());//公众号支付提供用户openid
+                        orderRequest.setOpenid(openId);//公众号支付提供用户openid
                         orderRequest.setBody("会员开通订单支付");
                         orderRequest.setOutTradeNo("appvip-" + storePayment.getPayCode());
                         orderRequest.setTotalFee(WxPayUnifiedOrderRequest.yuanToFen(storePayment.getPayMoney().toString()));//测试
@@ -290,7 +306,7 @@ public class FsUserVipOrderServiceImpl implements IFsUserVipOrderService
                         p.setLowOrderId("appvip-" + storePayment.getPayCode());
                         p.setBody("会员开通订单支付");
                         p.setIsMinipg("1");
-                        p.setOpenId(user.getMaOpenId());
+                        p.setOpenId(openId);
                         p.setAttach("");
                         p.setStoreid("0");
                         CreateWxOrderResult wxOrder = payService.createWxOrder(p);
@@ -314,7 +330,7 @@ public class FsUserVipOrderServiceImpl implements IFsUserVipOrderService
                         }
                         o.setPayerName("微信用户" + phone);
                         o.setGoodsInfo("会员开通订单支付"); // 订单信息
-                        o.setOpenId(user.getMaOpenId());
+                        o.setOpenId(openId);
                         o.setOrderType(5);
                         o.setOrderId(order.getOrderId().toString());
                         TzBankResult<PayCreateOrderResult> result = tzBankService.createOrder(o);
@@ -326,7 +342,7 @@ public class FsUserVipOrderServiceImpl implements IFsUserVipOrderService
                     } else if (payConfigDTO.getType().equals("hf")) {
                         HuiFuCreateOrder o = new HuiFuCreateOrder();
                         o.setTradeType("T_MINIAPP");
-                        o.setOpenid(user.getMaOpenId());
+                        o.setOpenid(openId);
                         o.setReqSeqId("appvip-" + storePayment.getPayCode());
                         o.setTransAmt(storePayment.getPayMoney().toString());
                         o.setGoodsDesc("会员开通订单支付");

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

@@ -0,0 +1,49 @@
+package com.fs.course.vo;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+@Data
+public class FsCoursePlaySourceConfigVO {
+
+    @ApiModelProperty("主键ID")
+    private Long id;
+
+    @ApiModelProperty("小程序/公众号名称")
+    private String name;
+
+    @ApiModelProperty("小程序/公众号appid")
+    private String appid;
+
+    @ApiModelProperty("小程序/公众号secret")
+    private String secret;
+
+    @ApiModelProperty("小程序/公众号icon图标")
+    private String img;
+
+    @ApiModelProperty("小程序/公众号原始id")
+    private String originalId;
+
+    @ApiModelProperty("token")
+    private String token;
+
+    @ApiModelProperty("aesKey")
+    private String aesKey;
+
+    @ApiModelProperty("msgDataFormat")
+    private String msgDataFormat;
+
+    @ApiModelProperty("类型 1小程序 2公众号")
+    private Integer type;
+
+    @ApiModelProperty("创建时间")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private LocalDateTime createTime;
+
+    @ApiModelProperty("修改时间")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private LocalDateTime updateTime;
+}

+ 2 - 0
fs-service/src/main/java/com/fs/course/vo/FsCourseWatchLogListVO.java

@@ -116,5 +116,7 @@ public class FsCourseWatchLogListVO extends BaseEntity
     private Long companyUserId;
     private Long courseId;
     private Long videoId;
+    private Integer isVip;
+
 
 }

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

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

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

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

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

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

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

@@ -15,7 +15,7 @@ public class PayConfigDTO implements Serializable {
     private String tzAppKey;
     private String tzPlatformPublicKey;
     private String tzPrivateKey;
-
+    private String appId;
 
 
 }

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

@@ -118,7 +118,7 @@ public interface FsPackageMapper
             "<if test = 'maps.diseaseType != null and maps.diseaseType !=0    '> " +
             "and p.disease_type = #{maps.diseaseType} " +
             "</if>" +
-            "<if test = 'maps.privateType != null and maps.privateType !=0    '> " +
+            "<if test = 'maps.privateType != null'> " +
             "and p.private_type = #{maps.privateType} " +
             "</if>" +
             "<if test = 'maps.isShow != null '> " +

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

@@ -41,4 +41,7 @@ public class FsPackageCateUParam implements Serializable
 
     private List<Integer> companyPackageCates;
 
+    private Long companyUserId;
+
+
 }

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

@@ -12,4 +12,7 @@ public class FsUserCouponSendParam {
 
     @Excel(name = "会员ID")
     private Long userId;
+
+    // 发送人id
+    private Long setSendUserId;
 }

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

@@ -26,4 +26,7 @@ public class WxSendRedPacketParam implements Serializable {
 
     private FsUser user;
 
+    private String mpAppId;
+
+
 }

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

@@ -6,6 +6,7 @@ import java.util.Map;
 import com.fs.his.domain.FsPackageCate;
 import com.fs.his.param.FsPackageCateUParam;
 import com.fs.his.vo.OptionsVO;
+import org.springframework.cache.annotation.CacheEvict;
 
 /**
  * 套餐包分类Service接口

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

@@ -173,7 +173,7 @@ public class FsExportTaskServiceImpl implements IFsExportTaskService
                 if (vo.getUserPhone() != null && isAdmin && vo.getUserPhone().length()>11) {
                     vo.setUserPhone(PhoneUtil.decryptPhone(vo.getUserPhone()));
                 }
-                if (vo.getUserAddress() != null) {
+                if (vo.getUserAddress() != null && !isAdmin) {
                     vo.setUserAddress(ParseUtils.parseAddress(vo.getUserAddress()));
                 }
             }

+ 7 - 0
fs-service/src/main/java/com/fs/his/service/impl/FsPackageCateServiceImpl.java

@@ -9,6 +9,8 @@ import com.fs.common.exception.CustomException;
 import com.fs.his.param.FsPackageCateUParam;
 import com.fs.his.vo.OptionsVO;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.cache.annotation.CacheEvict;
+import org.springframework.cache.annotation.Cacheable;
 import org.springframework.stereotype.Service;
 import com.fs.his.mapper.FsPackageCateMapper;
 import com.fs.his.domain.FsPackageCate;
@@ -45,6 +47,7 @@ public class FsPackageCateServiceImpl implements IFsPackageCateService
      * @return 套餐包分类
      */
     @Override
+    @Cacheable(value = "getPackagCateList", key = "#param")
     public List<FsPackageCate> selectFsPackageCateList(FsPackageCateUParam param)
     {
         return fsPackageCateMapper.selectFsPackageCateList(param);
@@ -57,6 +60,7 @@ public class FsPackageCateServiceImpl implements IFsPackageCateService
      * @return 结果
      */
     @Override
+    @CacheEvict(value = {"getPackageList","getPackagCateList"}, allEntries = true)
     public int insertFsPackageCate(FsPackageCate fsPackageCate)
     {
         Long cateCode = fsPackageCate.getCateCode();
@@ -75,6 +79,7 @@ public class FsPackageCateServiceImpl implements IFsPackageCateService
      * @return 结果
      */
     @Override
+    @CacheEvict(value = {"getPackageList","getPackagCateList"}, allEntries = true)
     public int updateFsPackageCate(FsPackageCate fsPackageCate)
     {
         Long cateCode = fsPackageCate.getCateCode();
@@ -93,6 +98,7 @@ public class FsPackageCateServiceImpl implements IFsPackageCateService
      * @return 结果
      */
     @Override
+    @CacheEvict(value = {"getPackageList","getPackagCateList"}, allEntries = true)
     public int deleteFsPackageCateByCateIds(Long[] cateIds)
     {
         return fsPackageCateMapper.deleteFsPackageCateByCateIds(cateIds);
@@ -105,6 +111,7 @@ public class FsPackageCateServiceImpl implements IFsPackageCateService
      * @return 结果
      */
     @Override
+    @CacheEvict(value = {"getPackageList","getPackagCateList"}, allEntries = true)
     public int deleteFsPackageCateByCateId(Long cateId)
     {
         return fsPackageCateMapper.deleteFsPackageCateByCateId(cateId);

+ 25 - 8
fs-service/src/main/java/com/fs/his/service/impl/FsPackageOrderServiceImpl.java

@@ -14,6 +14,8 @@ import cn.hutool.core.util.IdUtil;
 import cn.hutool.core.util.StrUtil;
 import cn.hutool.json.JSONUtil;
 import com.alibaba.fastjson.JSON;
+import com.baomidou.mybatisplus.core.conditions.Wrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.fs.common.constant.FsConstants;
 import com.fs.common.core.domain.AjaxResult;
 import com.fs.common.core.domain.R;
@@ -160,6 +162,8 @@ public class FsPackageOrderServiceImpl implements IFsPackageOrderService
     private IPayService ybPayService;
     @Autowired
     private IFsUserService fsUserService;
+    @Autowired
+    private FsUserWxMapper fsUserWxMapper;
 
     /**
      * 查询套餐订单
@@ -878,10 +882,23 @@ public class FsPackageOrderServiceImpl implements IFsPackageOrderService
         }
 
         FsUser user=userService.selectFsUserByUserId(param.getUserId());
-        if(user!=null&& StringUtils.isNotEmpty(user.getMaOpenId())){
+
+        String json = configService.selectConfigByKey("his.pay");
+        PayConfigDTO payConfigDTO = JSONUtil.toBean(json, PayConfigDTO.class);
+
+        String openId = Objects.isNull(user) ? "" : user.getMaOpenId();
+        if (StringUtils.isBlank(openId)){
+            Wrapper<FsUserWx> queryWrapper = Wrappers.<FsUserWx>lambdaQuery()
+                    .eq(FsUserWx::getFsUserId, param.getUserId())
+                    .eq(FsUserWx::getAppId, payConfigDTO.getAppId());
+            FsUserWx fsUserWx = fsUserWxMapper.selectOne(queryWrapper);
+            if (Objects.nonNull(fsUserWx)){
+                openId = fsUserWx.getOpenId();
+            }
+        }
+
+        if(user!=null&& StringUtils.isNotEmpty(openId)){
             if(fsPackageOrder.getPayMoney().compareTo(new BigDecimal(0))==1){
-                String json = configService.selectConfigByKey("his.pay");
-                PayConfigDTO payConfigDTO = JSONUtil.toBean(json, PayConfigDTO.class);
                 String payCode =  OrderCodeUtils.getOrderSn();
                 if(StringUtils.isEmpty(payCode)){
                     return R.error("订单生成失败,请重试");
@@ -898,7 +915,7 @@ public class FsPackageOrderServiceImpl implements IFsPackageOrderService
                 storePayment.setCompanyId(fsPackageOrder.getCompanyId());
                 storePayment.setCompanyUserId(fsPackageOrder.getCompanyUserId());
                 storePayment.setRemark("套餐包订单支付");
-                storePayment.setOpenId(user.getMaOpenId());
+                storePayment.setOpenId(openId);
                 storePayment.setUserId(user.getUserId());
                 storePayment.setStoreId(fsPackageOrder.getStoreId());
                 storePayment.setBusinessId(fsPackageOrder.getOrderId().toString());
@@ -917,7 +934,7 @@ public class FsPackageOrderServiceImpl implements IFsPackageOrderService
                         payConfig.setNotifyUrl(wxPayProperties.getNotifyUrl());
                         wxPayService.setConfig(payConfig);
                         WxPayUnifiedOrderRequest orderRequest = new WxPayUnifiedOrderRequest();
-                        orderRequest.setOpenid(user.getMaOpenId());//公众号支付提供用户openid
+                        orderRequest.setOpenid(openId);//公众号支付提供用户openid
                         orderRequest.setBody("套餐包订单支付");
                         orderRequest.setOutTradeNo("package-" + storePayment.getPayCode());
                         orderRequest.setTotalFee(WxPayUnifiedOrderRequest.yuanToFen(storePayment.getPayMoney().toString()));//测试
@@ -939,7 +956,7 @@ public class FsPackageOrderServiceImpl implements IFsPackageOrderService
                         p.setLowOrderId("package-" + storePayment.getPayCode());
                         p.setBody("套餐包订单支付");
                         p.setIsMinipg("1");
-                        p.setOpenId(user.getMaOpenId());
+                        p.setOpenId(openId);
                         p.setAttach("");
                         p.setStoreid("0");
                         CreateWxOrderResult wxOrder = payService.createWxOrder(p);
@@ -969,7 +986,7 @@ public class FsPackageOrderServiceImpl implements IFsPackageOrderService
                         }
                         o.setPayerName("微信用户"+phone);
                         o.setGoodsInfo("套餐包订单支付"); // 订单信息
-                        o.setOpenId(user.getMaOpenId());
+                        o.setOpenId(openId);
                         o.setOrderType(3);
                         o.setOrderId(fsPackageOrder.getOrderId().toString());
                         TzBankResult<PayCreateOrderResult> result = tzBankService.createOrder(o);
@@ -982,7 +999,7 @@ public class FsPackageOrderServiceImpl implements IFsPackageOrderService
                         logger.info("创建汇付订单");
                         HuiFuCreateOrder o = new HuiFuCreateOrder();
                         o.setTradeType("T_MINIAPP");
-                        o.setOpenid(user.getMaOpenId());
+                        o.setOpenid(openId);
                         o.setReqSeqId("package-"+storePayment.getPayCode());
                         o.setTransAmt(storePayment.getPayMoney().toString());
                         o.setGoodsDesc("套餐包订单支付");

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

@@ -27,6 +27,8 @@ import com.fs.system.oss.OSSFactory;
 import com.fs.system.service.ISysConfigService;
 import net.coobird.thumbnailator.Thumbnails;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.cache.annotation.CacheEvict;
+import org.springframework.cache.annotation.Cacheable;
 import org.springframework.stereotype.Service;
 import com.fs.his.mapper.FsPackageMapper;
 import com.fs.his.domain.FsPackage;
@@ -77,6 +79,7 @@ public class FsPackageServiceImpl implements IFsPackageService {
      * @return 结果
      */
     @Override
+    @CacheEvict(value = "getPackageList",allEntries = true)
     public int insertFsPackage(FsPackage fsPackage) {
 
         fsPackage.setCreateTime(DateUtils.getNowDate());
@@ -108,6 +111,7 @@ public class FsPackageServiceImpl implements IFsPackageService {
      */
     @Transactional(rollbackFor = Exception.class)
     @Override
+    @CacheEvict(value = "getPackageList",allEntries = true)
     public int updateFsPackage(FsPackage fsPackage) {
         fsPackage.setUpdateTime(DateUtils.getNowDate());
 //        if (fsPackage.getPackageSubType() != null && fsPackage.getPackageSubType() != 1) {
@@ -144,6 +148,7 @@ public class FsPackageServiceImpl implements IFsPackageService {
      * @return 结果
      */
     @Override
+    @CacheEvict(value = "getPackageList",allEntries = true)
     public int deleteFsPackageByPackageIds(Long[] packageIds) {
 
         return fsPackageMapper.deleteFsPackageByPackageIds(packageIds);
@@ -245,6 +250,7 @@ public class FsPackageServiceImpl implements IFsPackageService {
     }
 
     @Override
+    @Cacheable(value = "getPackageList", key = "#param")
     public List<FsPackageListUVO> selectFsPackageListUVO(FsPackageListUParam param) {
         return fsPackageMapper.selectFsPackageListUVO(param);
     }
@@ -255,6 +261,7 @@ public class FsPackageServiceImpl implements IFsPackageService {
     }
 
     @Override
+    @CacheEvict(value = "getPackageList",allEntries = true)
     public int updatePackagesStatus(Long[] packageIds, Long status) {
         return fsPackageMapper.updatePackagesStatus(packageIds, status);
     }

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

@@ -6,6 +6,8 @@ import cn.hutool.core.util.StrUtil;
 import cn.hutool.json.JSONArray;
 import cn.hutool.json.JSONUtil;
 import com.alibaba.fastjson.JSON;
+import com.baomidou.mybatisplus.core.conditions.Wrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.fs.common.core.domain.R;
 import com.fs.common.core.redis.RedisCache;
 import com.fs.common.exception.CustomException;
@@ -252,6 +254,8 @@ public class FsStoreOrderServiceImpl implements IFsStoreOrderService {
     private IFsPrescribeService fsPrescribeService;
     @Autowired
     private FsStoreOrderDfMapper fsStoreOrderDfMapper;
+    @Autowired
+    private FsUserWxMapper fsUserWxMapper;
 
     @Value("${express.omsCode}")
     private String expressOmsCode;
@@ -2567,15 +2571,28 @@ public class FsStoreOrderServiceImpl implements IFsStoreOrderService {
         }
 
         FsUser user = userService.selectFsUserByUserId(param.getUserId());
-        if (user != null && StringUtils.isNotEmpty(user.getMaOpenId())) {
+
+        //在线支付
+        String json = configService.selectConfigByKey("his.pay");
+        PayConfigDTO payConfigDTO = JSONUtil.toBean(json, PayConfigDTO.class);
+
+        String openId = Objects.isNull(user) ? "" : user.getMaOpenId();
+        if (StringUtils.isBlank(openId)){
+            Wrapper<FsUserWx> queryWrapper = Wrappers.<FsUserWx>lambdaQuery()
+                    .eq(FsUserWx::getFsUserId, param.getUserId())
+                    .eq(FsUserWx::getAppId, payConfigDTO.getAppId());
+            FsUserWx fsUserWx = fsUserWxMapper.selectOne(queryWrapper);
+            if (Objects.nonNull(fsUserWx)){
+                openId = fsUserWx.getOpenId();
+            }
+        }
+
+        if (user != null && StringUtils.isNotEmpty(openId)) {
 
             if (order.getPayMoney().compareTo(new BigDecimal(0)) == 0) {
                 this.payConfirm(order.getOrderCode(), "", "", "", 2);
                 return R.ok().put("data", param.getOrderId()).put("isPay", "1");
             } else {
-                //在线支付
-                String json = configService.selectConfigByKey("his.pay");
-                PayConfigDTO payConfigDTO = JSONUtil.toBean(json, PayConfigDTO.class);
                 String payCode = OrderCodeUtils.getOrderSn();
                 if (StringUtils.isEmpty(payCode)) {
                     return R.error("订单生成失败,请重试");
@@ -2590,7 +2607,7 @@ public class FsStoreOrderServiceImpl implements IFsStoreOrderService {
                 storePayment.setPayTypeCode("weixin");
                 storePayment.setBusinessType(2);
                 storePayment.setRemark("药品订单支付");
-                storePayment.setOpenId(user.getMaOpenId());
+                storePayment.setOpenId(openId);
                 storePayment.setUserId(user.getUserId());
                 storePayment.setCompanyId(order.getCompanyId());
                 storePayment.setCompanyUserId(order.getCompanyUserId());
@@ -2612,7 +2629,7 @@ public class FsStoreOrderServiceImpl implements IFsStoreOrderService {
                         payConfig.setNotifyUrl(wxPayProperties.getNotifyUrl());
                         wxPayService.setConfig(payConfig);
                         WxPayUnifiedOrderRequest orderRequest = new WxPayUnifiedOrderRequest();
-                        orderRequest.setOpenid(user.getMaOpenId());//公众号支付提供用户openid
+                        orderRequest.setOpenid(openId);//公众号支付提供用户openid
                         orderRequest.setBody("药品订单支付");
                         orderRequest.setOutTradeNo("store-" + storePayment.getPayCode());
                         orderRequest.setTotalFee(WxPayUnifiedOrderRequest.yuanToFen(storePayment.getPayMoney().toString()));//测试
@@ -2634,7 +2651,7 @@ public class FsStoreOrderServiceImpl implements IFsStoreOrderService {
                         p.setLowOrderId("store-" + storePayment.getPayCode());
                         p.setBody("药品订单支付");
                         p.setIsMinipg("1");
-                        p.setOpenId(user.getMaOpenId());
+                        p.setOpenId(openId);
                         p.setAttach("");
                         p.setStoreid("0");
                         CreateWxOrderResult wxOrder = payService.createWxOrder(p);
@@ -2663,7 +2680,7 @@ public class FsStoreOrderServiceImpl implements IFsStoreOrderService {
                         }
                         o.setPayerName("微信用户" + phone);
                         o.setGoodsInfo("药品订单支付"); // 订单信息
-                        o.setOpenId(user.getMaOpenId());
+                        o.setOpenId(openId);
                         o.setOrderType(2);
                         o.setOrderId(order.getOrderId().toString());
                         TzBankResult<PayCreateOrderResult> result = tzBankService.createOrder(o);
@@ -2675,7 +2692,7 @@ public class FsStoreOrderServiceImpl implements IFsStoreOrderService {
                     } else if (payConfigDTO.getType().equals("hf")) {
                         HuiFuCreateOrder o = new HuiFuCreateOrder();
                         o.setTradeType("T_MINIAPP");
-                        o.setOpenid(user.getMaOpenId());
+                        o.setOpenid(openId);
                         o.setReqSeqId("store-" + storePayment.getPayCode());
                         o.setTransAmt(storePayment.getPayMoney().toString());
                         o.setGoodsDesc("药品订单支付");

+ 52 - 28
fs-service/src/main/java/com/fs/his/service/impl/FsStorePaymentServiceImpl.java

@@ -8,6 +8,8 @@ import java.util.*;
 import cn.hutool.core.util.IdUtil;
 import cn.hutool.json.JSONUtil;
 import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.Wrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.fs.common.annotation.DataScope;
 import com.fs.common.annotation.Log;
 import com.fs.common.core.domain.AjaxResult;
@@ -30,15 +32,13 @@ import com.fs.course.service.IFsCourseRedPacketLogService;
 import com.fs.course.service.IFsUserCourseOrderService;
 import com.fs.course.service.IFsUserVipOrderService;
 import com.fs.erp.dto.ErpRefundUpdateRequest;
-import com.fs.his.domain.FsExportTask;
-import com.fs.his.domain.FsPayConfig;
-import com.fs.his.domain.FsStorePayment;
-import com.fs.his.domain.FsUser;
+import com.fs.his.domain.*;
 import com.fs.his.dto.PayConfigDTO;
 import com.fs.his.enums.PaymentMethodEnum;
 import com.fs.his.mapper.FsExportTaskMapper;
 import com.fs.his.mapper.FsStorePaymentMapper;
 import com.fs.his.mapper.FsUserMapper;
+import com.fs.his.mapper.FsUserWxMapper;
 import com.fs.his.param.FsStoreOrderParam;
 import com.fs.his.param.FsStorePaymentParam;
 import com.fs.his.param.PayOrderParam;
@@ -149,6 +149,8 @@ public class FsStorePaymentServiceImpl implements IFsStorePaymentService {
     private CompanyConfigMapper companyConfigMapper;
     @Autowired
     private FsUserMapper userMapper;
+    @Autowired
+    private FsUserWxMapper userWxMapper;
 
     /**
      * 查询支付明细
@@ -541,6 +543,12 @@ public class FsStorePaymentServiceImpl implements IFsStorePaymentService {
 
     // 内部方法:处理旧版本的发红包逻辑
     private R sendRedPacketLegacyInternal(WxSendRedPacketParam param, RedPacketConfig config) {
+        //如果服务号的配置存在,小程序红包接口可以使用服务号来发红包,重新赋值
+        //仅老商户支持
+        if (param.getUser().getMpOpenId()!=null && StringUtils.isNotEmpty(param.getMpAppId())){
+            config.setAppId(param.getMpAppId());
+            param.setOpenId(param.getUser().getMpOpenId());
+        }
         WxPayConfig payConfig = new WxPayConfig();
         BeanUtils.copyProperties(config, payConfig);
         WxPayService wxPayService = new WxPayServiceImpl();
@@ -550,6 +558,7 @@ public class FsStorePaymentServiceImpl implements IFsStorePaymentService {
         TransferBatchesRequest request = new TransferBatchesRequest();
         request.setAppid(config.getAppId());
 
+
         // todo 如果未配置负载均衡请还原原本的单号方式
 //        String code = IdUtil.getSnowflake(0, 0).nextIdStr();
         String code =  OrderCodeUtils.getOrderSn();
@@ -817,17 +826,17 @@ public class FsStorePaymentServiceImpl implements IFsStorePaymentService {
             throw new CustomException("用户不存在");
         }
 
+        String json = configService.selectConfigByKey("his.pay");
+        logger.debug("支付配置 his.pay: {}", json);
+        FsPayConfig payConfig = JSONUtil.toBean(json, FsPayConfig.class);
+
         if (isWechatPayment(payOrderParam.getPaymentMethod())) {
-            String openId = getOpenIdForPaymentMethod(user, payOrderParam.getPaymentMethod());
+            String openId = getOpenIdForPaymentMethod(user, payOrderParam.getPaymentMethod(), payConfig);
             if (StringUtils.isBlank(openId)){
                 throw new CustomException("用户OPENID不存在");
             }
         }
 
-        String json = configService.selectConfigByKey("his.pay");
-        logger.debug("支付配置 his.pay: {}", json);
-        FsPayConfig payConfig = JSONUtil.toBean(json, FsPayConfig.class);
-
         // 创建记录
         FsStorePayment storePayment = createStorePayment(payConfig, user, payOrderParam);
 
@@ -841,13 +850,13 @@ public class FsStorePaymentServiceImpl implements IFsStorePaymentService {
     private R createThirdPartyPayment(FsPayConfig payConfig, FsStorePayment storePayment, FsUser user, PayOrderParam payOrderParam) {
         switch (payConfig.getType()) {
             case "wx":
-                return createWxPayment(payConfig, storePayment, user, payOrderParam);
+                return createWxPayment(storePayment, user, payOrderParam, payConfig);
             case "yb":
-                return createYbPayment(storePayment, user, payOrderParam);
+                return createYbPayment(storePayment, user, payOrderParam, payConfig);
             case "tz":
-                return createTzPayment(storePayment, user, payOrderParam);
+                return createTzPayment(storePayment, user, payOrderParam, payConfig);
             case "hf":
-                return createHfPayment(storePayment, user, payOrderParam);
+                return createHfPayment(storePayment, user, payOrderParam, payConfig);
             default:
                 throw new CustomException("不支持的支付方式");
         }
@@ -856,7 +865,7 @@ public class FsStorePaymentServiceImpl implements IFsStorePaymentService {
     /**
      * 汇付
      */
-    private R createHfPayment(FsStorePayment storePayment, FsUser user, PayOrderParam payOrderParam) {
+    private R createHfPayment(FsStorePayment storePayment, FsUser user, PayOrderParam payOrderParam, FsPayConfig payConfig) {
         logger.debug("创建汇付订单");
 
         HuiFuCreateOrder order = new HuiFuCreateOrder();
@@ -867,7 +876,7 @@ public class FsStorePaymentServiceImpl implements IFsStorePaymentService {
 
         // 微信支付需要设置openid
         if (isWechatPayment(payOrderParam.getPaymentMethod())) {
-            order.setOpenid(getOpenIdForPaymentMethod(user, payOrderParam.getPaymentMethod()));
+            order.setOpenid(getOpenIdForPaymentMethod(user, payOrderParam.getPaymentMethod(), payConfig));
         }
 
         HuifuCreateOrderResult result = huiFuService.createOrder(order);
@@ -897,8 +906,8 @@ public class FsStorePaymentServiceImpl implements IFsStorePaymentService {
     /**
      * 台州银行
      */
-    private R createTzPayment(FsStorePayment storePayment, FsUser user, PayOrderParam payOrderParam) {
-        PayCreateOrder payOrder = buildTzPayOrder(storePayment, user, payOrderParam);
+    private R createTzPayment(FsStorePayment storePayment, FsUser user, PayOrderParam payOrderParam, FsPayConfig payConfig) {
+        PayCreateOrder payOrder = buildTzPayOrder(storePayment, user, payOrderParam, payConfig);
         TzBankResult<PayCreateOrderResult> result = tzBankService.createOrder(payOrder);
 
         updateStorePaymentTradeNo(storePayment.getPaymentId(), result.getBody().getOrderFlowNo());
@@ -908,7 +917,7 @@ public class FsStorePaymentServiceImpl implements IFsStorePaymentService {
     /**
      * 构建台州银行支付
      */
-    private PayCreateOrder buildTzPayOrder(FsStorePayment storePayment, FsUser user, PayOrderParam payOrderParam) {
+    private PayCreateOrder buildTzPayOrder(FsStorePayment storePayment, FsUser user, PayOrderParam payOrderParam, FsPayConfig payConfig) {
         PayCreateOrder payOrder = new PayCreateOrder();
         payOrder.setOrderNo(payOrderParam.getBusinessType().getPrefix() + "-" + storePayment.getPayCode());
         payOrder.setTrxAmt(storePayment.getPayMoney().doubleValue());
@@ -929,7 +938,7 @@ public class FsStorePaymentServiceImpl implements IFsStorePaymentService {
         }
 
         if (isWechatPayment(payOrderParam.getPaymentMethod())) {
-            payOrder.setOpenId(getOpenIdForPaymentMethod(user, payOrderParam.getPaymentMethod()));
+            payOrder.setOpenId(getOpenIdForPaymentMethod(user, payOrderParam.getPaymentMethod(), payConfig));
         }
 
         return payOrder;
@@ -980,7 +989,7 @@ public class FsStorePaymentServiceImpl implements IFsStorePaymentService {
     /**
      * 易宝支付
      */
-    private R createYbPayment(FsStorePayment storePayment, FsUser user, PayOrderParam payOrderParam) {
+    private R createYbPayment(FsStorePayment storePayment, FsUser user, PayOrderParam payOrderParam, FsPayConfig payConfig) {
         PaymentMethodEnum paymentMethod = payOrderParam.getPaymentMethod();
         if (paymentMethod == PaymentMethodEnum.ALIPAY || paymentMethod == PaymentMethodEnum.H5_ALIPAY
                 || paymentMethod == PaymentMethodEnum.H5_WECHAT) {
@@ -992,7 +1001,7 @@ public class FsStorePaymentServiceImpl implements IFsStorePaymentService {
         payDto.setLowOrderId(payOrderParam.getBusinessType().getPrefix() + "-" + storePayment.getPayCode());
         payDto.setBody(payOrderParam.getBusinessType().getDesc());
         payDto.setIsMinipg("1");
-        payDto.setOpenId(getOpenIdForPaymentMethod(user, paymentMethod));
+        payDto.setOpenId(getOpenIdForPaymentMethod(user, paymentMethod, payConfig));
         payDto.setAttach("");
         payDto.setStoreid("0");
 
@@ -1020,7 +1029,7 @@ public class FsStorePaymentServiceImpl implements IFsStorePaymentService {
     /**
      * 微信支付
      */
-    private R createWxPayment(FsPayConfig payConfig, FsStorePayment storePayment, FsUser user, PayOrderParam payOrderParam) {
+    private R createWxPayment(FsStorePayment storePayment, FsUser user, PayOrderParam payOrderParam, FsPayConfig payConfig) {
         PaymentMethodEnum paymentMethod = payOrderParam.getPaymentMethod();
         if (paymentMethod != PaymentMethodEnum.MINIAPP_WECHAT) {
             logger.debug("微信支付 PaymentMethod: {}", paymentMethod.name());
@@ -1031,7 +1040,7 @@ public class FsStorePaymentServiceImpl implements IFsStorePaymentService {
         wxPayService.setConfig(wxPayConfig);
 
         WxPayUnifiedOrderRequest orderRequest = new WxPayUnifiedOrderRequest();
-        orderRequest.setOpenid(getOpenIdForPaymentMethod(user, paymentMethod));
+        orderRequest.setOpenid(getOpenIdForPaymentMethod(user, paymentMethod, payConfig));
         orderRequest.setBody(payOrderParam.getBusinessType().getDesc());
         orderRequest.setOutTradeNo(payOrderParam.getBusinessType().getPrefix() + "-" + storePayment.getPayCode());
         orderRequest.setTotalFee(WxPayUnifiedOrderRequest.yuanToFen(storePayment.getPayMoney().toString()));
@@ -1074,15 +1083,30 @@ public class FsStorePaymentServiceImpl implements IFsStorePaymentService {
     /**
      * 根据支付方式获取对应的openId
      */
-    private String getOpenIdForPaymentMethod(FsUser user, PaymentMethodEnum method) {
+    private String getOpenIdForPaymentMethod(FsUser user, PaymentMethodEnum method, FsPayConfig payConfig) {
+        String openId;
         switch (method) {
             case MINIAPP_WECHAT:
-                return user.getMaOpenId();
+                openId = user.getMaOpenId();
+                break;
             case H5_WECHAT:
-                return user.getMpOpenId();
+                openId = user.getMpOpenId();
+                break;
             default:
-                return null;
+                openId = null;
         }
+
+        if (StringUtils.isBlank(openId)) {
+            Wrapper<FsUserWx> queryWrapper = Wrappers.<FsUserWx>lambdaQuery()
+                    .eq(FsUserWx::getFsUserId, user.getUserId())
+                    .eq(FsUserWx::getAppId, payConfig.getAppId());
+            FsUserWx fsUserWx = userWxMapper.selectOne(queryWrapper);
+            if (Objects.nonNull(fsUserWx)) {
+                openId = fsUserWx.getOpenId();
+            }
+        }
+
+        return openId;
     }
 
     /**
@@ -1112,7 +1136,7 @@ public class FsStorePaymentServiceImpl implements IFsStorePaymentService {
 
         // 设置openId(如果是微信支付)
         if (isWechatPayment(payOrderParam.getPaymentMethod())) {
-            storePayment.setOpenId(getOpenIdForPaymentMethod(user, payOrderParam.getPaymentMethod()));
+            storePayment.setOpenId(getOpenIdForPaymentMethod(user, payOrderParam.getPaymentMethod(), payConfig));
         }
 
         if (fsStorePaymentMapper.insertFsStorePayment(storePayment) <= 0) {

+ 6 - 5
fs-service/src/main/java/com/fs/his/service/impl/FsUserCouponServiceImpl.java

@@ -122,8 +122,6 @@ public class FsUserCouponServiceImpl implements IFsUserCouponService
     @Transactional
     @Override
     public int sendFsUserCoupon(FsUserCouponSendParam param) {
-
-
         if (param.getUserId()==null){
             throw new CustomException("用户不能为空");
         }
@@ -148,9 +146,12 @@ public class FsUserCouponServiceImpl implements IFsUserCouponService
         fsUserCoupon.setCouponCode("C"+System.currentTimeMillis());
         fsUserCoupon.setUserId(param.getUserId());
         fsUserCoupon.setCreateTime(DateUtils.getNowDate());
-
-        fsUserCoupon.setSendUserId( SecurityUtils.getUserId());
-        System.out.println("发送人id"+ SecurityUtils.getUserId());
+        if (param.getSetSendUserId() != null){
+            fsUserCoupon.setSendUserId(param.getSetSendUserId());
+        } else {
+            fsUserCoupon.setSendUserId( SecurityUtils.getUserId());
+        }
+        System.out.println("发送人id:"+ fsUserCoupon.getSendUserId());
         fsUserCoupon.setStatus(0);
         int i = fsUserCouponMapper.insertFsUserCoupon(fsUserCoupon);
         coupon.setRemainNumber(coupon.getRemainNumber()-1);

+ 18 - 7
fs-service/src/main/java/com/fs/his/service/impl/FsUserIntegralLogsServiceImpl.java

@@ -231,15 +231,26 @@ public class FsUserIntegralLogsServiceImpl implements IFsUserIntegralLogsService
             System.out.println("User ID: " + param.getUserId());
 
             //判断是否在限额类型内
-            if (Arrays.asList(integralTypeByOneDay).contains(param.getLogType())){
-                Integer todayTotalIntegral= fsUserIntegralLogsMapper.selectTodayTotalIntegral(integralTypeByOneDay,param.getUserId());
-                if (todayTotalIntegral==null){
-                    todayTotalIntegral=0;
-                }
-                if (todayTotalIntegral>=config.getIntegralByOneDay()){
-                    return R.error("当天积分已达限额");
+            if (integralTypeByOneDay != null) {
+                if (Arrays.asList(integralTypeByOneDay).contains(param.getLogType())){
+                    Integer todayTotalIntegral= fsUserIntegralLogsMapper.selectTodayTotalIntegral(integralTypeByOneDay,param.getUserId());
+                    if (todayTotalIntegral==null){
+                        todayTotalIntegral=0;
+                    }
+                    if (todayTotalIntegral>=config.getIntegralByOneDay()){
+                        return R.error("当天积分已达限额");
+                    }
                 }
             }
+//            if (Arrays.asList(integralTypeByOneDay).contains(param.getLogType())){
+//                Integer todayTotalIntegral= fsUserIntegralLogsMapper.selectTodayTotalIntegral(integralTypeByOneDay,param.getUserId());
+//                if (todayTotalIntegral==null){
+//                    todayTotalIntegral=0;
+//                }
+//                if (todayTotalIntegral>=config.getIntegralByOneDay()){
+//                    return R.error("当天积分已达限额");
+//                }
+//            }
             Integer integralNum = null;
             FsUserIntegralLogTypeEnum logsType = null;
             List<FsUserIntegralLogs> integralLogs;

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

@@ -572,11 +572,15 @@ public class FsUserServiceImpl implements IFsUserService
 
         List<SysDictData> courseProject = dictDataMapper.selectDictDataByType("sys_course_project");
         for (FsUserPageListVO fsUserPageListVO : fsUserPageListVOS) {
-            // 项目
-            courseProject.stream()
-                    .filter(c -> c.getDictValue().equals(fsUserPageListVO.getProjectId().toString()))
-                    .findFirst()
-                    .ifPresent(c -> fsUserPageListVO.setProjectName(c.getDictLabel()));
+            if (courseProject != null && !courseProject.isEmpty()) {
+                if (fsUserPageListVO.getProjectId() != null){
+                    // 项目
+                    courseProject.stream()
+                            .filter(c -> c.getDictValue().equals(fsUserPageListVO.getProjectId().toString()))
+                            .findFirst()
+                            .ifPresent(c -> fsUserPageListVO.setProjectName(c.getDictLabel()));
+                }
+            }
             if (StringUtils.isEmpty(fsUserPageListVO.getNickname())){
                 fsUserPageListVO.setNickname("用户暂未授权昵称");
             }

+ 1 - 1
fs-service/src/main/java/com/fs/qw/mapper/QwUserMapper.java

@@ -43,7 +43,7 @@ public interface QwUserMapper extends BaseMapper<QwUser>
 
     public List<QwUser> batchGetQwUser(@Param("list") List<QwUserKeyDTO> qwUserId);
 
-    @Select("select company_user_id,company_id,welcome_text,qw_user_name from qw_user where id = #{id}")
+    @Select("select company_user_id,company_id,welcome_text,qw_user_name,send_msg_type from qw_user where id = #{id}")
     public QwUser selectQwUserByIdByWeComeText(@Param("id") Long id);
 
     @Select("select * from qw_user where qw_user_id = #{qwUserId} and corp_id = #{corpId} ")

+ 1 - 1
fs-service/src/main/java/com/fs/qw/service/impl/QwUserVoiceLogServiceImpl.java

@@ -135,7 +135,7 @@ public class QwUserVoiceLogServiceImpl extends ServiceImpl<QwUserVoiceLogMapper,
 
             qwUserVoiceLogTotalVos.forEach(m-> {
                 companyUserList.forEach(n-> {
-                    if(m.getCompanyUserId().equals(n.getUserId())){
+                    if(m.getCompanyUserId() != null && n.getUserId() != null && m.getCompanyUserId().equals(n.getUserId())){
                         m.setCompanyUserName(n.getNickName());
                     }
                 });

+ 1 - 0
fs-service/src/main/java/com/fs/qw/vo/QwUserVoiceLogTotalVo.java

@@ -51,6 +51,7 @@ public class QwUserVoiceLogTotalVo extends BaseEntity {
     private String corpId;
 
 
+
     /** 公司id */
     //@Excel(name = "公司id")
     private Long companyId;

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

@@ -321,7 +321,7 @@ public interface QwSopLogsMapper extends BaseMapper<QwSopLogs> {
     @DataSource(DataSourceType.SOP)
     List<QwSopLogs> selectIpadByCorpId(@Param("corpId") String corpId, @Param("now") LocalDateTime now);
 
-    @DataSource(DataSourceType.SOP)
+    @DataSource(DataSourceType.SopREAD)
     List<QwSopLogs> selectByQwUserId(@Param("id") Long id);
 
     @Select("select * from qw_sop_logs where send_type=8 and send_status=3 and  create_time <= DATE_SUB(NOW(), INTERVAL 2 HOUR) ")

+ 3 - 2
fs-service/src/main/java/com/fs/sop/service/impl/QwSopTempServiceImpl.java

@@ -398,11 +398,12 @@ public class QwSopTempServiceImpl implements IQwSopTempService
                     rules.setIsOfficial("0");
                 }
 
-                if (day.getDayNum()==1){
+                if (day.getDayNum()==1 && sorts.get() == 0 && temp.getOpenOfficial().equals("1")){
                     rules.setTime("01:05");
+                }else {
+                    rules.setTime(time);
                 }
 
-                rules.setTime(time);
                 rules.setContentType(2);
                 rules.setType(2);
                 rules.setCourseType(0);

+ 6 - 5
fs-service/src/main/java/com/fs/sop/service/impl/SopUserLogsInfoServiceImpl.java

@@ -745,10 +745,10 @@ public class SopUserLogsInfoServiceImpl implements ISopUserLogsInfoService {
             String companyId = String.valueOf(qwUser.getCompanyId()).trim();
 
             //域名
-            String domainName = companyUserMapper.selectDomainByUserId(Long.parseLong(companyUserId));
-            if (StringUtils.isEmpty(domainName)){
-                domainName = config.getRealLinkDomainName();
-            }
+//            String domainName = companyUserMapper.selectDomainByUserId(Long.parseLong(companyUserId));
+//            if (StringUtils.isEmpty(domainName)){
+//                domainName = config.getRealLinkDomainName();
+//            }
 
             QwCompany qwCompany = iQwCompanyService.getQwCompanyByRedis(param.getCorpId());
 
@@ -757,7 +757,8 @@ public class SopUserLogsInfoServiceImpl implements ISopUserLogsInfoService {
             }
 
 
-            String finalDomainName = domainName;
+            String finalDomainName = "domainName";
+
             sopUserLogsInfos.forEach(item->{
 
                 QwSopLogs sopLogs=new QwSopLogs();

+ 1 - 1
fs-service/src/main/resources/application-config-druid-hdt.yml

@@ -77,7 +77,7 @@ tencent_cloud_config:
   region: ap-chongqing
   proxy: hdt
 cloud_host:
-  company_name: 弘德
+  company_name: 弘德
 #看课授权时显示的头像
 headerImg:
   imgUrl: https://jz-cos-1356808054.cos.ap-chengdu.myqcloud.com/fs/20250515/0877754b59814ea8a428fa3697b20e68.png

+ 2 - 1
fs-service/src/main/resources/application-config-druid-qdtst.yml

@@ -87,7 +87,8 @@ cloud_host:
 headerImg:
   imgUrl: https://qdtst-1360717104.cos.ap-nanjing.myqcloud.com/qdtst-1360717104/20250624/937019e4090f46788ef29c4e7df479c3.jpg
 ipad:
-  ipadUrl: http://ipad.cdwjyyh.com
+  ipadUrl:
+  aiApi:
 wx_miniapp_temp:
   pay_order_temp_id:
   inquiry_temp_id:

+ 87 - 0
fs-service/src/main/resources/application-config-druid-syysy-test.yml

@@ -0,0 +1,87 @@
+baidu:
+  token: 1
+  back-domain: https://www.xxxx.com
+#配置
+logging:
+  level:
+    org.springframework.web: INFO
+    com.github.binarywang.demo.wx.cp: DEBUG
+    me.chanjar.weixin: DEBUG
+wx:
+  miniapp:
+    configs:
+      - appid: w   #中康智慧
+        secret: 5
+        token: Ncbnd7lJvkripVOpyTFAna6NAWCxCrvC
+        aesKey: HlEiBB55eaWUaeBVAQO3cWKWPYv1vOVQSq7nFNICw4E
+        msgDataFormat: JSON
+      - appid: w   #中康未来智慧药房
+        secret: 9
+        token: Ncbnd7lJvkripVOpyTFAna6NAWCxCrvC
+        aesKey: HlEiBB55eaWUaeBVAQO3cWKWPYv1vOVQSq7nFNICw4E
+        msgDataFormat: JSON
+  cp:
+    corpId: wwb
+    appConfigs:
+      - agentId: 100005
+        secret: ec7okROXJqkNafq66aKNv0asTzQIG0CYrj3vyBbo
+        token: PPKOdAloMO
+        aesKey: PKvaxtpSvNGpfTDm7VUHIK8Wok2ESyYX24qpXJAdMP
+  pay:
+    appId: wx #微信公众号或者小程序等的appid
+    mchId: 1611045 #微信支付商户号
+    mchKey: 8cab128997a3547c10898b877f38 #微信支付商户密钥
+    subAppId:  #服务商模式下的子商户公众账号ID
+    subMchId:  #服务商模式下的子商户号
+    keyPath: c:\\cert\\apiclient_cert.p12 # p12证书的位置,可以指定绝对路径,也可以指定类路径(以classpath:开头)
+    notifyUrl: https://usepp.his.runtzh.com/app/wxpay/wxPayNotify
+  mp:
+    useRedis: false
+    redisConfig:
+      host: 127.0.0.1
+      port: 6379
+      timeout: 2000
+    configs:
+      - appId: wx # 第一个公众号的appid  //公众号名称
+        secret: 5da9ae # 公众号的appsecret
+        token: PPKOdAlCoMO # 接口配置里的Token值
+        aesKey: Eswa6VjwtVcw03qZy6Wllgrv5aytIA1SZPEU0kU2 # 接口配置里的EncodingAESKey值
+aifabu:  #爱链接
+  appKey: 7b471be905ab17ef358c610dd117601d008
+watch:
+  watchUrl: watch.ylrzcloud.com/prod-api
+#  account: tcloud
+#  password: mdf-m2h_6yw2$hq
+  account1: ccif #866655060138751
+  password1: cp-t5or_6xw7$mt
+  account2: tcloud #rt500台
+  password2: mdf-m2h_6yw2$hq
+  account3: whr
+  password3: v9xsKuqn_$d2y
+
+fs :
+  commonApi: http://159.75.111.224:8010
+  h5CommonApi: http://159.75.111.224:8010
+nuonuo:
+  key: 10924508
+  secret: A2EB20764D304D16
+# 存储捅配置
+tencent_cloud_config:
+  secret_id: AKIDiMq9lDf2EOM9lIfqqfKo7FNgM5meD0sT
+  secret_key: u5SuS80342xzx8FRBukza9lVNHKNMSaB
+  bucket: syysy-1323137866
+  app_id: 1323137866
+  region: ap-chongqing
+  proxy: syysy
+cloud_host:
+  company_name: 益善缘
+#看课授权时显示的头像
+headerImg:
+  imgUrl: https://ysy-1329817240.cos.ap-guangzhou.myqcloud.com/ysy/20250820/2c47e4f105b641b4a49df50a77338e32.png
+ipad:
+  ipadUrl: http://ipad.ysya.top
+  aiApi:
+wx_miniapp_temp:
+  pay_order_temp_id:
+  inquiry_temp_id:
+

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

@@ -60,8 +60,8 @@ watch:
   password3: v9xsKuqn_$d2y
 
 fs :
-  commonApi: http://172.27.0.12:8010
-  h5CommonApi: http://172.27.0.12:8010
+  commonApi: http://159.75.111.224:8010
+  h5CommonApi: http://159.75.111.224:8010
 nuonuo:
   key: 10924508
   secret: A2EB20764D304D16
@@ -77,9 +77,9 @@ cloud_host:
   company_name: 益善缘
 #看课授权时显示的头像
 headerImg:
-  imgUrl: https://jz-cos-1356808054.cos.ap-chengdu.myqcloud.com/fs/20250515/0877754b59814ea8a428fa3697b20e68.png
+  imgUrl: https://ysy-1329817240.cos.ap-guangzhou.myqcloud.com/ysy/20250820/2c47e4f105b641b4a49df50a77338e32.png
 ipad:
-  ipadUrl: http://ipad.xintaihl.cn
+  ipadUrl: http://ipad.ysya.top
   aiApi:
 wx_miniapp_temp:
   pay_order_temp_id:

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

@@ -162,3 +162,4 @@ token:
 openIM:
     secret: openIM123
     userID: imAdmin
+    url: web.im.ysya.top

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

@@ -0,0 +1,172 @@
+# 数据源配置
+spring:
+    profiles:
+        include: config-druid-jzzx,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://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@.
+                read:
+                    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
+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

+ 5 - 1
fs-service/src/main/resources/application-druid-jzzx.yml

@@ -99,6 +99,10 @@ spring:
                     url: jdbc:mysql://192.168.0.137:3306/sop?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
                     username: root
                     password: Ylrztek250218!3@.
+                read:
+                    url: jdbc:mysql://192.168.0.138:3306/sop?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
+                    username: root
+                    password: Ylrztek250218!3@.
                 # 初始连接数
                 initialSize: 5
                 # 最小连接池数量
@@ -165,4 +169,4 @@ token:
     expireTime: 180
 openIM:
     secret: openIM123
-    userID: imAdmin
+    userID: imAdmin

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

@@ -0,0 +1,168 @@
+# 数据源配置
+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
+custom:
+    token: "1o62d"
+    encoding-aes-key: "UJfTQ5qKTK"
+    corp-id: "ww517"
+    secret: "6ODAmw-"
+    private-key-path: ""
+    webhook-url: ""
+# token配置
+token:
+    # 令牌自定义标识
+    header: Authorization
+    # 令牌密钥
+    secret: abcdefghijklmnopqrstuvwxyz
+    # 令牌有效期(默认30分钟)
+    expireTime: 180
+openIM:
+    secret:
+    userID:

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

@@ -148,3 +148,21 @@ rocketmq:
         group: test-group
         access-key: ak1243b25nj17d4b2dc1a03 # 替换为实际的 accessKey
         secret-key: sk08a7ea1f9f4b0237 # 替换为实际的 secretKey
+custom:
+    token: "1o62d"
+    encoding-aes-key: "UJfTQ5qKTK"
+    corp-id: "ww517"
+    secret: "6ODAmw-"
+    private-key-path: ""
+    webhook-url: ""
+# token配置
+token:
+    # 令牌自定义标识
+    header: Authorization
+    # 令牌密钥
+    secret: abcdefghijklmnopqrstuvwxyz
+    # 令牌有效期(默认30分钟)
+    expireTime: 180
+openIM:
+    secret:
+    userID:

+ 166 - 0
fs-service/src/main/resources/application-druid-syysy-test.yml

@@ -0,0 +1,166 @@
+# 数据源配置
+spring:
+    profiles:
+        include: config-druid-syysy-test,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.199.225.59:2345/fs_his?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
+                    username: root
+                    password: Ylrz_tM818782145I@
+                # 从库数据源
+                slave:
+                    # 从数据源开关/默认关闭
+                    url: jdbc:mysql://139.199.225.59:2345/fs_his?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
+                    username: root
+                    password: Ylrz_tM818782145I@
+                # 初始连接数
+                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://172.16.0.7:3306/sop?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
+                    username: root
+                    password: Ylrz_tM818782145I@
+                # 初始连接数
+                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
+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
+    url: https://web.im.ysya.top/api

+ 11 - 11
fs-service/src/main/resources/application-druid-syysy.yml

@@ -1,15 +1,15 @@
 # 数据源配置
 spring:
     profiles:
-        include: config-druid-sxjz,common
+        include: config-druid-syysy,common
     # redis 配置
     redis:
-        host: 172.27.0.13
+        host: 172.16.0.13
         port: 6379
         # 数据库索引
         database: 0
         # 密码
-        password: Sxdtcbm@#+!2025
+        password: Ylrz_tM8/oW6$pU9|tJ#&
         # 连接超时时间
         timeout: 10s
         lettuce:
@@ -39,16 +39,15 @@ spring:
             druid:
                 # 主库数据源
                 master:
-                    url: jdbc:mysql://172.27.0.6:3306/fs_his?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
+                    url: jdbc:mysql://172.16.0.7:3306/fs_his?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
                     username: root
-                    password: Sxdtcbm@#+!2025
+                    password: Ylrz_tM818782145I@
                 # 从库数据源
                 slave:
                     # 从数据源开关/默认关闭
-                    enabled: false
-                    url:
-                    username:
-                    password:
+                    url: jdbc:mysql://172.16.0.16:3306/fs_his?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
+                    username: root
+                    password: Ylrz_tM818782145I@
                 # 初始连接数
                 initialSize: 5
                 # 最小连接池数量
@@ -94,9 +93,9 @@ spring:
             druid:
                 # 主库数据源
                 master:
-                    url: jdbc:mysql://172.27.0.6:3306/fs_his_sop?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
+                    url: jdbc:mysql://172.16.0.7:3306/sop?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
                     username: root
-                    password: Sxdtcbm@#+!2025
+                    password: Ylrz_tM818782145I@
                 # 初始连接数
                 initialSize: 5
                 # 最小连接池数量
@@ -164,3 +163,4 @@ token:
 openIM:
     secret: openIM123
     userID: imAdmin
+    url: https://web.im.ysya.top/api

+ 1 - 1
fs-service/src/main/resources/application-druid-yzt.yml

@@ -7,7 +7,7 @@ spring:
         host: r-wz9syugp027unhsdmepd.redis.rds.aliyuncs.com
         port: 6333
         # 数据库索引
-        database: 0
+        database: 12
         # 密码
         password: minzhong:Jc6m85WC7iMeULn7
         # 连接超时时间

+ 33 - 0
fs-service/src/main/resources/db/20250821-点播播放源配置改造.sql

@@ -0,0 +1,33 @@
+-- 点播播放源配置表
+drop table if exists `fs_course_play_source_config`;
+create table `fs_course_play_source_config` (
+    `id`            bigint not null auto_increment       comment '主键ID',
+    `name`          varchar(255) not null                comment '小程序/公众号名称',
+    `appid`         varchar(50)  not null                comment '小程序/公众号appid',
+    `secret`        varchar(64)  not null                comment '小程序/公众号secret',
+    `img`           varchar(512)                         comment '小程序/公众号icon图标',
+    `original_id`   varchar(20)                          comment '小程序/公众号原始id',
+    `token`         varchar(255)  not null               comment 'token',
+    `aes_key`       varchar(255)  not null               comment 'aesKey',
+    `msg_data_format` varchar(255)  not null             comment 'msgDataFormat',
+    `type`          tinyint default 1                    comment '类型 1小程序 2公众号',
+    `is_del`        tinyint(1) default 0                 comment '是否删除 0正常 1删除',
+    `create_time`   datetime                             comment '创建时间',
+    `update_time`   datetime                             comment '修改时间',
+    primary key (`id`) using btree,
+    key idx_appid (`appid`),
+    key idx_is_del (`is_del`),
+    key idx_update (`update_time`)
+) engine = Innodb comment '点播播放源配置表';
+
+-- 字典
+INSERT INTO `sys_dict_type`
+    (`dict_name`, `dict_type`, `status`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`)
+VALUES
+    ('点播播放源类型', 'play_source_type', '0', 'admin', '2021-11-24 23:26:40', '', NULL, '点播播放源类型');
+
+INSERT INTO `sys_dict_data`
+    (`dict_sort`, `dict_label`, `dict_value`, `dict_type`, `css_class`, `list_class`, `is_default`, `status`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`)
+VALUES
+    (1, '小程序', '1', 'play_source_type', '', '', 'Y', '0', 'admin', '2021-11-24 23:26:40', '', NULL, '小程序'),
+    (2, '公众号', '2', 'play_source_type', '', '', 'Y', '0', 'admin', '2021-11-24 23:26:40', '', NULL, '公众号');

+ 20 - 0
fs-service/src/main/resources/mapper/course/FsCoursePlaySourceConfigMapper.xml

@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.fs.course.mapper.FsCoursePlaySourceConfigMapper">
+
+    <select id="selectCoursePlaySourceConfigVOListByMap" resultType="com.fs.course.vo.FsCoursePlaySourceConfigVO">
+        select
+            fcpsc.*
+        from fs_course_play_source_config fcpsc
+        where fcpsc.is_del = 0
+        <if test="params.name != null and params.name != ''">
+            and fcpsc.name like concat('%', #{params.name}, '%')
+        </if>
+        <if test="params.appid != null and params.appid != ''">
+            and fcpsc.appid like concat('%', #{params.appid}, '%')
+        </if>
+        order by fcpsc.id desc
+    </select>
+</mapper>

+ 5 - 1
fs-service/src/main/resources/mapper/course/FsCourseWatchLogMapper.xml

@@ -58,7 +58,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         select l.log_id,l.user_id,uc.course_name,v.title as video_name,qec.avatar as external_user_avatar,
         l.log_type,SEC_TO_TIME(l.duration) as duration,c.company_name,l.camp_period_time,l.finish_time,
         cu.nick_name as company_user_name ,l.send_type,l.create_time,l.update_time,l.last_heartbeat_time,
-        qu.qw_user_name,qec.name as external_user_name,c.company_id,u.avatar as fsAvatar,u.nick_name as fsNickName,qec.create_time as qec_create_time
+        qu.qw_user_name,qec.name as external_user_name,c.company_id,u.avatar as fsAvatar,u.nick_name as fsNickName,qec.create_time as qec_create_time,
+        u.is_vip isVip
          from fs_course_watch_log l
          left join fs_user_course_video v on v.video_id = l.video_id
          left join fs_user_course uc on uc.course_id = l.course_id
@@ -68,6 +69,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
          LEFT JOIN qw_user qu on qu.id= l.qw_user_id
          LEFT JOIN qw_external_contact qec on l.qw_external_contact_id = qec.id
         <where>
+            <if test ='maps.isVip !=null'>
+                and l.user_id != 0 and u.is_vip = #{maps.isVip}
+            </if>
             <if test ='maps.sendType !=null'>
                 and l.send_type = #{maps.sendType}
             </if>

+ 76 - 0
fs-service/src/main/resources/mapper/fastGpt/FastgptChatArtificialWordsMapper.xml

@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.fs.fastGpt.mapper.FastgptChatArtificialWordsMapper">
+    
+    <resultMap type="FastgptChatArtificialWords" id="FastgptChatArtificialWordsResult">
+        <result property="id"    column="id"    />
+        <result property="type"    column="type"    />
+        <result property="content"    column="content"    />
+        <result property="status"    column="status"    />
+        <result property="sort"    column="sort"    />
+        <result property="createTime"    column="create_time"    />
+    </resultMap>
+
+    <sql id="selectFastgptChatArtificialWordsVo">
+        select id, `type`, content, status, sort, create_time from fastgpt_chat_artificial_words
+    </sql>
+
+    <select id="selectFastgptChatArtificialWordsList" parameterType="FastgptChatArtificialWords" resultMap="FastgptChatArtificialWordsResult">
+        <include refid="selectFastgptChatArtificialWordsVo"/>
+        <where>  
+            <if test="type != null "> and `type` = #{type}</if>
+            <if test="content != null  and content != ''"> and content = #{content}</if>
+            <if test="status != null "> and status = #{status}</if>
+            <if test="sort != null "> and sort = #{sort}</if>
+        </where>
+        order by sort asc,id desc
+    </select>
+    
+    <select id="selectFastgptChatArtificialWordsById" parameterType="Long" resultMap="FastgptChatArtificialWordsResult">
+        <include refid="selectFastgptChatArtificialWordsVo"/>
+        where id = #{id}
+    </select>
+        
+    <insert id="insertFastgptChatArtificialWords" parameterType="FastgptChatArtificialWords" useGeneratedKeys="true" keyProperty="id">
+        insert into fastgpt_chat_artificial_words
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="type != null">`type`,</if>
+            <if test="content != null">content,</if>
+            <if test="status != null">status,</if>
+            <if test="sort != null">sort,</if>
+            <if test="createTime != null">create_time,</if>
+         </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="type != null">#{type},</if>
+            <if test="content != null">#{content},</if>
+            <if test="status != null">#{status},</if>
+            <if test="sort != null">#{sort},</if>
+            <if test="createTime != null">#{createTime},</if>
+         </trim>
+    </insert>
+
+    <update id="updateFastgptChatArtificialWords" parameterType="FastgptChatArtificialWords">
+        update fastgpt_chat_artificial_words
+        <trim prefix="SET" suffixOverrides=",">
+            <if test="type != null">type = #{type},</if>
+            <if test="content != null">content = #{content},</if>
+            <if test="status != null">status = #{status},</if>
+            <if test="sort != null">sort = #{sort},</if>
+            <if test="createTime != null">create_time = #{createTime},</if>
+        </trim>
+        where id = #{id}
+    </update>
+
+    <delete id="deleteFastgptChatArtificialWordsById" parameterType="Long">
+        delete from fastgpt_chat_artificial_words where id = #{id}
+    </delete>
+
+    <delete id="deleteFastgptChatArtificialWordsByIds" parameterType="String">
+        delete from fastgpt_chat_artificial_words where id in 
+        <foreach item="id" collection="array" open="(" separator="," close=")">
+            #{id}
+        </foreach>
+    </delete>
+</mapper>

+ 1 - 0
fs-service/src/main/resources/mapper/his/FsArticleCateMapper.xml

@@ -38,6 +38,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         <if test="params.status != null">
             and status = #{params.status}
         </if>
+        order by sort asc
     </select>
 
     <insert id="insertFsArticleCate" parameterType="FsArticleCate" useGeneratedKeys="true" keyProperty="cateId">

+ 2 - 2
fs-service/src/main/resources/mapper/his/FsUserMapper.xml

@@ -1009,7 +1009,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         SELECT
         (
         SELECT
-        count(fs_user.user_id )
+        count(distinct fs_user.user_id )
         FROM
         fs_course_answer_logs
         LEFT JOIN fs_user ON fs_user.user_id = fs_course_answer_logs.user_id
@@ -1043,7 +1043,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         ) AS answerNum,
         (
         SELECT
-        count(fs_user.user_id )
+        count(distinct fs_user.user_id )
         FROM
         fs_course_answer_logs
         LEFT JOIN fs_user ON fs_user.user_id = fs_course_answer_logs.user_id

+ 22 - 14
fs-service/src/main/resources/mapper/qw/QwUserVoiceLogMapper.xml

@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8" ?>
 <!DOCTYPE mapper
-PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
-"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 <mapper namespace="com.fs.qw.mapper.QwUserVoiceLogMapper">
 
     <resultMap type="QwUserVoiceLog" id="QwUserVoiceLogResult">
@@ -19,13 +19,14 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 
     <resultMap type="com.fs.qw.vo.QwUserVoiceLogTotalVo" id="QwUserVoiceLogVoTotalResult">
         <result property="id"    column="id"    />
-        <result property="qwUserId"    column="qw_user_id"    />
+        <result property="corpId"    column="corp_id"    />
         <result property="duration"    column="duration"    />
         <result property="connectCount"    column="connectCount"    />
         <result property="noConnectCount"    column="noConnectCount"    />
         <result property="createTime"     column="create_time"     />
+        <result property="companyUserId"     column="company_user_id"     />
         <association property="qwUser" javaType="com.fs.qw.domain.QwUser" autoMapping="true">
-            <id column="qw_uer_id" property="qwUserId"></id>
+            <id column="qw_user_id" property="qwUserId"></id>
             <result column="qw_user_name" property="qwUserName"></result>
         </association>
     </resultMap>
@@ -86,19 +87,26 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
     <select id="selectQwUserVoiceLogTotalList" resultMap="QwUserVoiceLogVoTotalResult">
 
         SELECT
-        SUM(duration) duration,qu.qw_user_name,
+        SUM(duration) duration,qu.qw_user_name,uvl.corp_id,qu.qw_user_id,uvl.company_user_id,
         COUNT(CASE WHEN uvl.status=1 THEN 1 END) AS connectCount,
         COUNT(CASE WHEN uvl.status=2 THEN 1 END) AS noConnectCount
         FROM qw_user_voice_log uvl
         LEFT JOIN qw_user qu ON uvl.qw_user_id = qu.id
-        where  uvl.company_id = #{companyId}
-        <if test="qwUserName != null ">and qu.qw_user_name like concat(#{qwUserName}, '%')</if>
-        <if test="beginTime != null and endTime != null">
-            AND date_format(uvl.create_time,'%Y-%m-%d') &gt;= #{beginTime}
-            AND date_format(uvl.create_time,'%Y-%m-%d') &lt;= #{endTime}
+        <where>
+            <if test="companyId != null ">and uvl.company_id = #{companyId}</if>
+            <if test="companyUserId != null ">and uvl.company_user_id = #{companyUserId}</if>
+            <if test="qwUserName != null ">and qu.qw_user_name like concat(#{qwUserName}, '%')</if>
+            <if test="beginTime != null and endTime != null">
+                AND date_format(uvl.create_time,'%Y-%m-%d') &gt;= #{beginTime}
+                AND date_format(uvl.create_time,'%Y-%m-%d') &lt;= #{endTime}
+            </if>
+        </where>
+        <if test="qwUserId != null">
+            group by qu.qw_user_id,uvl.corp_id,uvl.qw_user_id
+        </if>
+        <if test="qwUserId == null">
+            group by qu.company_user_id
         </if>
-
-        group by qu.qw_user_name
 
     </select>
 
@@ -115,7 +123,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="companyId != null">company_id,</if>
             <if test="companyUserId != null">company_user_id,</if>
             <if test="createTime != null">create_time,</if>
-         </trim>
+        </trim>
         <trim prefix="values (" suffix=")" suffixOverrides=",">
             <if test="extId != null">#{extId},</if>
             <if test="qwUserId != null">#{qwUserId},</if>
@@ -126,7 +134,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="companyId != null">#{companyId},</if>
             <if test="companyUserId != null">#{companyUserId},</if>
             <if test="createTime != null">#{createTime},</if>
-         </trim>
+        </trim>
     </insert>
 
     <update id="updateQwUserVoiceLog" parameterType="QwUserVoiceLog">

+ 0 - 1
fs-user-app/src/main/java/com/fs/FsUserAppApplication.java

@@ -20,7 +20,6 @@ public class FsUserAppApplication
 {
     public static void main(String[] args)
     {
-
         // System.setProperty("spring.devtools.restart.enabled", "false");
         SpringApplication.run(FsUserAppApplication.class, args);
         System.out.println("AppAPI启动成功");

+ 18 - 0
fs-user-app/src/main/java/com/fs/app/controller/AppLoginController.java

@@ -25,6 +25,7 @@ import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import lombok.Synchronized;
 import org.apache.commons.lang3.StringUtils;
+import org.apache.ibatis.annotations.Param;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -402,4 +403,21 @@ public class AppLoginController extends AppBaseController{
             return R.error("用户不存在!");
         }
     }
+
+    /**
+     * 更新jpushId
+     */
+    @Login
+    @GetMapping("/updatePushId")
+    public R updatePushId(@Param("pushId") String pushId) {
+        String userId = getUserId();
+        FsUser fsUser = new FsUser();
+        fsUser.setUserId(Long.parseLong(userId));
+        fsUser.setJpushId(pushId);
+        if (userMapper.updateFsUser(fsUser)>0) {
+            return R.ok();
+        } else {
+            return R.error("用户不存在!");
+        }
+    }
 }

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

@@ -91,10 +91,15 @@ public class CouponController extends  AppBaseController {
      * 发送会员优惠券
      */
     @RepeatSubmit
-    @Log(title = "发送会员优惠券", businessType = BusinessType.INSERT)
+    @Login
     @PostMapping("/sendCoupon")
     public AjaxResult sendCoupon(@RequestBody FsUserCouponSendParam fsUserCoupon)
     {
+        Long companyUserId = getCompanyUserId();
+        if(companyUserId==null){
+            return AjaxResult.error("销售未登录!");
+        }
+        fsUserCoupon.setSetSendUserId(companyUserId);
         return toAjax(fsUserCouponService.sendFsUserCoupon(fsUserCoupon));
     }
 

+ 34 - 6
fs-user-app/src/main/java/com/fs/app/controller/InquiryOrderController.java

@@ -3,10 +3,13 @@ package com.fs.app.controller;
 
 import cn.hutool.core.util.IdUtil;
 import cn.hutool.json.JSONUtil;
+import com.baomidou.mybatisplus.core.conditions.Wrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.fs.app.annotation.Login;
 import com.fs.common.annotation.RepeatSubmit;
 import com.fs.common.core.domain.R;
 import com.fs.common.exception.CustomException;
+import com.fs.common.utils.CloudHostUtils;
 import com.fs.common.utils.ParseUtils;
 import com.fs.common.utils.StringUtils;
 import com.fs.common.utils.ip.IpUtils;
@@ -17,6 +20,7 @@ import com.fs.his.domain.*;
 import com.fs.his.dto.FsInquiryOrderPatientDTO;
 import com.fs.his.dto.PayConfigDTO;
 import com.fs.his.enums.FsInquiryOrderStatusEnum;
+import com.fs.his.mapper.FsUserWxMapper;
 import com.fs.his.param.*;
 import com.fs.his.service.*;
 import com.fs.his.utils.PhoneUtil;
@@ -102,6 +106,8 @@ public class InquiryOrderController extends  AppBaseController {
     Logger logger= LoggerFactory.getLogger(getClass());
     @Autowired
     private ICompanyService companyService;
+    @Autowired
+    private FsUserWxMapper fsUserWxMapper;
 
     @Autowired
     private ISysConfigService configService;
@@ -170,7 +176,13 @@ public class InquiryOrderController extends  AppBaseController {
         }
 
         FsUser user=userService.selectFsUserByUserId(Long.parseLong(getUserId()));
-        if(user!=null&& StringUtils.isNotEmpty(user.getMaOpenId())){
+        if(user!=null){
+
+            // 红德堂特殊处理
+            if (!CloudHostUtils.isCloudHostName("弘德堂") && StringUtils.isBlank(user.getMaOpenId())) {
+                return R.error("用户OPENID不存在");
+            }
+
             if(param.getUserCouponId()!=null&&param.getUserCouponId()>0l){
                 FsUserCoupon userCoupon=userCouponService.selectFsUserCouponById(param.getUserCouponId());
                 if(userCoupon==null){
@@ -237,6 +249,22 @@ public class InquiryOrderController extends  AppBaseController {
         FsInquiryOrder order=inquiryOrderService.selectFsInquiryOrderByOrderId(param.getOrderId());
 
         FsUser user=userService.selectFsUserByUserId(Long.parseLong(getUserId()));
+
+        String openId = Objects.isNull(user) ? "" : user.getMaOpenId();
+        if (StringUtils.isBlank(openId)){
+            Wrapper<FsUserWx> queryWrapper = Wrappers.<FsUserWx>lambdaQuery()
+                    .eq(FsUserWx::getFsUserId, Long.parseLong(getUserId()))
+                    .eq(FsUserWx::getAppId, payConfigDTO.getAppId());
+            FsUserWx fsUserWx = fsUserWxMapper.selectOne(queryWrapper);
+            if (Objects.nonNull(fsUserWx)){
+                openId = fsUserWx.getOpenId();
+            }
+        }
+
+        if (StringUtils.isBlank(openId)){
+            return R.error("用户OPENID不存在");
+        }
+
         if(order.getPayMoney().compareTo(new BigDecimal(0))==0){
             inquiryOrderService.payConfirm(order.getOrderSn(),"","","",2);
             return R.ok().put("isPay",1);
@@ -258,7 +286,7 @@ public class InquiryOrderController extends  AppBaseController {
             storePayment.setPayTypeCode("weixin");
             storePayment.setBusinessType(1);
             storePayment.setRemark("问诊订单支付");
-            storePayment.setOpenId(user.getMaOpenId());
+            storePayment.setOpenId(openId);
             storePayment.setUserId(user.getUserId());
             storePayment.setBusinessId(order.getOrderId().toString());
             if(storePaymentService.insertFsStorePayment(storePayment)>0){
@@ -276,7 +304,7 @@ public class InquiryOrderController extends  AppBaseController {
                     payConfig.setNotifyUrl(wxPayProperties.getNotifyUrl());
                     wxPayService.setConfig(payConfig);
                     WxPayUnifiedOrderRequest orderRequest = new WxPayUnifiedOrderRequest();
-                    orderRequest.setOpenid(user.getMaOpenId());//公众号支付提供用户openid
+                    orderRequest.setOpenid(openId);//公众号支付提供用户openid
                     orderRequest.setBody("问诊订单支付");
                     orderRequest.setOutTradeNo("inquiry-"+storePayment.getPayCode());
                     orderRequest.setTotalFee(WxPayUnifiedOrderRequest.yuanToFen(storePayment.getPayMoney().toString()));//测试
@@ -299,7 +327,7 @@ public class InquiryOrderController extends  AppBaseController {
                     p.setLowOrderId("inquiry-"+storePayment.getPayCode());
                     p.setBody("问诊订单支付");
                     p.setIsMinipg("1");
-                    p.setOpenId(user.getMaOpenId());
+                    p.setOpenId(openId);
                     p.setAttach("");
                     p.setStoreid("0");
                     CreateWxOrderResult wxOrder = payService.createWxOrder(p);
@@ -330,7 +358,7 @@ public class InquiryOrderController extends  AppBaseController {
                     }
                     o.setPayerName("微信用户"+phone);
                     o.setGoodsInfo("问诊订单支付"); // 订单信息
-                    o.setOpenId(user.getMaOpenId());
+                    o.setOpenId(openId);
                     o.setOrderType(1);
                     o.setOrderId(order.getOrderId().toString());
                     TzBankResult<PayCreateOrderResult> result = tzBankService.createOrder(o);
@@ -342,7 +370,7 @@ public class InquiryOrderController extends  AppBaseController {
                 }else if(payConfigDTO.getType().equals("hf")){
                     HuiFuCreateOrder o = new HuiFuCreateOrder();
                     o.setTradeType("T_MINIAPP");
-                    o.setOpenid(user.getMaOpenId());
+                    o.setOpenid(openId);
                     o.setReqSeqId("inquiry-"+storePayment.getPayCode());
                     o.setTransAmt(storePayment.getPayMoney().toString());
                     o.setGoodsDesc("问诊订单支付");

+ 2 - 2
fs-user-app/src/main/java/com/fs/app/controller/PackageController.java

@@ -67,9 +67,9 @@ public class PackageController extends AppBaseController {
     private ICompanyService companyService;
 
     @ApiOperation("获取套餐分类")
-    @Cacheable(value = "getPackagCateList", key = "#param")
     @GetMapping("/getPackagCateList")
     public R getPackagCateList(FsPackageCateUParam param) {
+        log.info("获取套餐分类: {} ",param);
         try {
             ObjectMapper objectMapper = new ObjectMapper();
             Long companyUserId = getCompanyUserId();
@@ -80,6 +80,7 @@ public class PackageController extends AppBaseController {
             if (param.getType()==2){
                 param.setCompanyPackageCates(cateIdList);
             }
+            param.setCompanyUserId(companyUserId);
         } catch (Exception e) {
             log.info("获取套餐分类:销售未登录");
         } finally {
@@ -90,7 +91,6 @@ public class PackageController extends AppBaseController {
     }
 
     @ApiOperation("获取套餐列表")
-    @Cacheable(value = "getPackageList", key = "#param")
     @GetMapping("/getPackageList")
     public R getPackageList(FsPackageListUParam param) {
         PageHelper.startPage(param.getPageNum(), param.getPageSize());

+ 18 - 0
fs-user-app/src/main/java/com/fs/app/controller/UserController.java

@@ -34,6 +34,7 @@ import com.google.zxing.WriterException;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.ibatis.annotations.Param;
 import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.validation.annotation.Validated;
@@ -293,4 +294,21 @@ public class UserController extends  AppBaseController {
         return getDataTable(list);
     }
 
+    /**
+     * 更新historyApp
+     */
+    @Login
+    @GetMapping("/updateHistoryApp")
+    public R updateHistoryApp(@Param("historyApp") String historyApp) {
+        String userId = getUserId();
+        FsUser fsUser = new FsUser();
+        fsUser.setUserId(Long.parseLong(userId));
+//        fsUser.setHistoryApp(historyApp);
+        if (userService.updateFsUser(fsUser)>0) {
+            return R.ok();
+        } else {
+            return R.error("用户不存在!");
+        }
+    }
+
 }

+ 2 - 0
fs-user-app/src/main/java/com/fs/app/controller/WxUserController.java

@@ -145,6 +145,7 @@ public class WxUserController extends AppBaseController{
                     //写入
                     user=new FsUser();
                     user.setPhone(phoneNoInfo.getPhoneNumber());
+                    user.setNickname("微信用户"+phoneNoInfo.getPhoneNumber().substring(phoneNoInfo.getPhoneNumber().length()-4));
                     user.setNickName("微信用户"+phoneNoInfo.getPhoneNumber().substring(phoneNoInfo.getPhoneNumber().length()-4));
                     user.setAvatar("https://hos-1309931967.cos.ap-chongqing.myqcloud.com/fs/20230725/a848605591384ec29d49773dd58d9345.jpg");
                     user.setStatus(1);
@@ -251,6 +252,7 @@ public class WxUserController extends AppBaseController{
                     //写入
                     user=new FsUser();
                     user.setPhone(phoneNoInfo.getPhoneNumber());
+                    user.setNickname("微信用户"+phoneNoInfo.getPhoneNumber().substring(phoneNoInfo.getPhoneNumber().length()-4));
                     user.setNickName("微信用户"+phoneNoInfo.getPhoneNumber().substring(phoneNoInfo.getPhoneNumber().length()-4));
                     user.setAvatar("https://hos-1309931967.cos.ap-chongqing.myqcloud.com/fs/20230725/a848605591384ec29d49773dd58d9345.jpg");
                     user.setStatus(1);

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

@@ -68,7 +68,7 @@ import java.util.concurrent.TimeUnit;
 @RequestMapping(value="/store/app/storeOrder")
 public class StoreOrderScrmController extends AppBaseController {
 
-    private static final String STORE_PAY_CONF = "store.pay";
+    private static final String STORE_PAY_CONF = "his.pay";
 
     Logger logger= LoggerFactory.getLogger(getClass());
 

+ 4 - 1
fs-user-app/src/main/java/com/fs/framework/aspectj/UserOperationLogAspect.java

@@ -82,7 +82,10 @@ public class UserOperationLogAspect {
                     operationLog.setDetails(details.toString());
                 }
             }
-            logMapper.insertFsUserOperationLog(operationLog);
+
+            if (operationLog.getUserId() != null) {
+                logMapper.insertFsUserOperationLog(operationLog);
+            }
         } catch (Exception ex) {
             log.error("操作日志插入异常", ex);
         } finally {

+ 9 - 2
fs-user-app/src/main/java/com/fs/framework/config/SecurityConfig.java

@@ -6,10 +6,11 @@ import org.springframework.security.config.BeanIds;
 import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
 import org.springframework.security.config.annotation.web.builders.HttpSecurity;
 import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
+import org.springframework.security.web.firewall.StrictHttpFirewall;
 
 /**
  * spring security配置
- * 
+ *
 
  */
 @EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
@@ -45,6 +46,12 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter
     public AuthenticationManager authenticationManagerBean() throws Exception {
         return super.authenticationManagerBean();
     }
-
+    @Bean
+    public StrictHttpFirewall httpFirewall() {
+        StrictHttpFirewall firewall = new StrictHttpFirewall();
+        // 允许URL编码的双斜杠
+        firewall.setAllowUrlEncodedDoubleSlash(true);
+        return firewall;
+    }
 
 }