Ver Fonte

Merge branch 'master' into 红德堂APP调试

Long há 4 dias atrás
pai
commit
482dab5d26
73 ficheiros alterados com 2449 adições e 51 exclusões
  1. 38 0
      fs-admin/src/main/java/com/fs/course/controller/FsVideoResourceController.java
  2. 114 0
      fs-admin/src/main/java/com/fs/his/controller/FsPhysicalReportTemplateController.java
  3. 140 0
      fs-admin/src/main/java/com/fs/his/controller/FsPhysicalReportTemplateFieldController.java
  4. 6 0
      fs-admin/src/main/java/com/fs/his/controller/FsStoreOrderController.java
  5. 7 1
      fs-admin/src/main/java/com/fs/his/task/Task.java
  6. 11 0
      fs-admin/src/main/java/com/fs/qw/qwTask/qwTask.java
  7. 67 0
      fs-company-app/src/main/java/com/fs/app/controller/FsUserCoursePeriodController.java
  8. 46 0
      fs-company-app/src/main/java/com/fs/app/controller/qw/QwFsCourseWatchLogController.java
  9. 2 0
      fs-company/src/main/java/com/fs/company/controller/qw/QwMaterialController.java
  10. 4 5
      fs-company/src/main/java/com/fs/company/controller/qw/SopUserLogsInfoController.java
  11. 7 0
      fs-company/src/main/java/com/fs/company/controller/store/FsStoreOrderController.java
  12. 1 1
      fs-ipad-task/src/main/java/com/fs/app/task/SendMsg.java
  13. 5 3
      fs-qw-task/src/main/java/com/fs/app/controller/CommonController.java
  14. 73 0
      fs-qwhook-sop/src/main/java/com/fs/app/controller/ApisQwMaterialBySidebar.java
  15. 72 0
      fs-qwhook-sop/src/main/java/com/fs/app/controller/QwMaterialBySidebar.java
  16. 81 0
      fs-qwhook/src/main/java/com/fs/app/controller/ApisQwMaterialBySidebar.java
  17. 73 0
      fs-qwhook/src/main/java/com/fs/app/controller/QwMaterialBySidebar.java
  18. 1 1
      fs-service/src/main/java/com/fs/course/service/IFsUserCoursePeriodDaysService.java
  19. 16 1
      fs-service/src/main/java/com/fs/course/service/impl/FsUserCoursePeriodDaysServiceImpl.java
  20. 3 0
      fs-service/src/main/java/com/fs/course/service/impl/FsUserCourseVideoServiceImpl.java
  21. 3 0
      fs-service/src/main/java/com/fs/erp/domain/ErpGoods.java
  22. 10 0
      fs-service/src/main/java/com/fs/erp/dto/OrderItemDTO.java
  23. 2 1
      fs-service/src/main/java/com/fs/erp/http/JstErpHttpService.java
  24. 14 1
      fs-service/src/main/java/com/fs/erp/http/JstErpHttpServiceImpl.java
  25. 75 1
      fs-service/src/main/java/com/fs/erp/service/impl/JSTErpGoodsServiceImpl.java
  26. 3 0
      fs-service/src/main/java/com/fs/erp/service/impl/JSTErpOrderServiceImpl.java
  27. 22 2
      fs-service/src/main/java/com/fs/erp/service/impl/JstTokenService.java
  28. 32 0
      fs-service/src/main/java/com/fs/his/domain/FsPhysicalReportTemplate.java
  29. 72 0
      fs-service/src/main/java/com/fs/his/domain/FsPhysicalReportTemplateField.java
  30. 4 0
      fs-service/src/main/java/com/fs/his/domain/FsStoreProduct.java
  31. 19 0
      fs-service/src/main/java/com/fs/his/dto/FsPhysicalReportTemplateFieldDTO.java
  32. 6 0
      fs-service/src/main/java/com/fs/his/mapper/FsInquiryOrderReportMapper.java
  33. 75 0
      fs-service/src/main/java/com/fs/his/mapper/FsPhysicalReportTemplateFieldMapper.java
  34. 61 0
      fs-service/src/main/java/com/fs/his/mapper/FsPhysicalReportTemplateMapper.java
  35. 7 1
      fs-service/src/main/java/com/fs/his/mapper/FsStoreProductAttrValueMapper.java
  36. 6 0
      fs-service/src/main/java/com/fs/his/mapper/FsStoreProductMapper.java
  37. 5 0
      fs-service/src/main/java/com/fs/his/param/FsInquiryOrderCreateParam.java
  38. 4 0
      fs-service/src/main/java/com/fs/his/param/FsStoreProductAddEditParam.java
  39. 80 0
      fs-service/src/main/java/com/fs/his/service/IFsPhysicalReportTemplateFieldService.java
  40. 61 0
      fs-service/src/main/java/com/fs/his/service/IFsPhysicalReportTemplateService.java
  41. 7 0
      fs-service/src/main/java/com/fs/his/service/IFsStoreProductAttrValueService.java
  42. 7 0
      fs-service/src/main/java/com/fs/his/service/IFsStoreProductService.java
  43. 1 1
      fs-service/src/main/java/com/fs/his/service/impl/FsInquiryOrderServiceImpl.java
  44. 153 0
      fs-service/src/main/java/com/fs/his/service/impl/FsPhysicalReportTemplateFieldServiceImpl.java
  45. 125 0
      fs-service/src/main/java/com/fs/his/service/impl/FsPhysicalReportTemplateServiceImpl.java
  46. 5 2
      fs-service/src/main/java/com/fs/his/service/impl/FsStoreOrderServiceImpl.java
  47. 5 0
      fs-service/src/main/java/com/fs/his/service/impl/FsStoreProductAttrValueServiceImpl.java
  48. 50 6
      fs-service/src/main/java/com/fs/his/service/impl/FsStoreProductServiceImpl.java
  49. 11 2
      fs-service/src/main/java/com/fs/qw/domain/QwMaterial.java
  50. 5 1
      fs-service/src/main/java/com/fs/qw/mapper/QwMaterialMapper.java
  51. 6 1
      fs-service/src/main/java/com/fs/qw/param/QwMaterialParam.java
  52. 28 0
      fs-service/src/main/java/com/fs/qw/param/QwMaterialParamBySidebar.java
  53. 8 0
      fs-service/src/main/java/com/fs/qw/service/IQwMaterialService.java
  54. 147 7
      fs-service/src/main/java/com/fs/qw/service/impl/QwMaterialServiceImpl.java
  55. 8 0
      fs-service/src/main/java/com/fs/sop/domain/SopUserLogsInfo.java
  56. 1 1
      fs-service/src/main/java/com/fs/sop/mapper/SopUserLogsMapper.java
  57. 3 1
      fs-service/src/main/java/com/fs/sop/service/impl/QwSopTempServiceImpl.java
  58. 4 4
      fs-service/src/main/java/com/fs/sop/service/impl/SopUserLogsInfoServiceImpl.java
  59. 92 0
      fs-service/src/main/resources/application-config-druid-bjczwh.yml
  60. 3 2
      fs-service/src/main/resources/application-config-druid-bnkc.yml
  61. 1 0
      fs-service/src/main/resources/application-config-druid-drk.yml
  62. 1 0
      fs-service/src/main/resources/application-config-druid-whhm.yml
  63. 1 0
      fs-service/src/main/resources/application-config-druid-xfk.yml
  64. 3 3
      fs-service/src/main/resources/application-config-druid-xzt.yml
  65. 149 0
      fs-service/src/main/resources/application-druid-bjczwh.yml
  66. 175 0
      fs-service/src/main/resources/mapper/his/FsPhysicalReportTemplateFieldMapper.xml
  67. 81 0
      fs-service/src/main/resources/mapper/his/FsPhysicalReportTemplateMapper.xml
  68. 4 0
      fs-service/src/main/resources/mapper/his/FsStoreProductAttrValueMapper.xml
  69. 10 1
      fs-service/src/main/resources/mapper/his/FsStoreProductMapper.xml
  70. 10 0
      fs-service/src/main/resources/mapper/qw/QwMaterialMapper.xml
  71. 9 0
      fs-store/src/main/java/com/fs/store/controller/store/FsStoreOrderController.java
  72. 5 0
      fs-user-app/src/main/java/com/fs/app/controller/course/CourseFsUserController.java
  73. 3 1
      fs-user-app/src/main/java/com/fs/app/controller/course/CourseFsUserLoginController.java

+ 38 - 0
fs-admin/src/main/java/com/fs/course/controller/FsVideoResourceController.java

@@ -17,6 +17,7 @@ import org.springframework.web.bind.annotation.*;
 
 import java.time.LocalDateTime;
 import java.util.*;
+import java.util.stream.Collectors;
 
 /**
  * 资源库管理
@@ -102,6 +103,43 @@ public class FsVideoResourceController extends BaseController {
         return AjaxResult.success();
     }
 
+    /**
+     * 批量修改视频分类
+     * @param typeId
+     * @param typeSubId
+     * @param ids
+     * @return
+     */
+    @PreAuthorize("@ss.hasPermi('course:videoResource:batchUpdateClass')")
+    @Log(title = "视频素材库", businessType = BusinessType.UPDATE)
+    @PostMapping("/batchUpdateClass")
+    public AjaxResult batchUpdateClass(@RequestParam("typeId") Long typeId,
+                                       @RequestParam("typeSubId") Long typeSubId,
+                                       @RequestParam("ids") String ids) {
+        if(typeId == null || typeId <= 0){
+            return AjaxResult.error("请选择分类");
+        }
+        if(typeSubId == null || typeSubId <= 0){
+            return AjaxResult.error("请选择子分类");
+        }
+        if(ids == null || ids.isEmpty()){
+            return AjaxResult.error("请选择要修改的分类");
+        }
+
+        // 将ids字符串分割为ID列表
+        List<String> idList = Arrays.asList(ids.split(","));
+
+        // 创建更新条件
+        Wrapper<FsVideoResource> updateWrapper = Wrappers.<FsVideoResource>lambdaUpdate()
+                .set(FsVideoResource::getTypeId, typeId)
+                .set(FsVideoResource::getTypeSubId, typeSubId)
+                .in(FsVideoResource::getId, idList.stream().map(Long::valueOf).collect(Collectors.toList()));
+
+        // 执行批量更新
+        fsVideoResourceService.update(updateWrapper);
+        return AjaxResult.success();
+    }
+
     @PreAuthorize("@ss.hasPermi('course:videoResource:batchAdd')")
     @Log(title = "视频素材库", businessType = BusinessType.INSERT)
     @PostMapping("/batchAddVideoResource")

+ 114 - 0
fs-admin/src/main/java/com/fs/his/controller/FsPhysicalReportTemplateController.java

@@ -0,0 +1,114 @@
+package com.fs.his.controller;
+
+import java.util.List;
+
+import com.fs.common.core.domain.model.LoginUser;
+import com.fs.common.utils.ServletUtils;
+import com.fs.framework.web.service.TokenService;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.fs.common.annotation.Log;
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.enums.BusinessType;
+import com.fs.his.domain.FsPhysicalReportTemplate;
+import com.fs.his.service.IFsPhysicalReportTemplateService;
+import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.common.core.page.TableDataInfo;
+
+/**
+ * 体检报告模板Controller
+ * 
+ * @author fs
+ * @date 2025-07-23
+ */
+@RestController
+@RequestMapping("/his/physicalReportTemplate")
+public class FsPhysicalReportTemplateController extends BaseController
+{
+    @Autowired
+    private IFsPhysicalReportTemplateService fsPhysicalReportTemplateService;
+
+    @Autowired
+    private TokenService tokenService;
+
+    /**
+     * 查询体检报告模板列表
+     */
+    @PreAuthorize("@ss.hasPermi('his:physicalReportTemplate:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(FsPhysicalReportTemplate fsPhysicalReportTemplate)
+    {
+        startPage();
+        List<FsPhysicalReportTemplate> list = fsPhysicalReportTemplateService.selectFsPhysicalReportTemplateList(fsPhysicalReportTemplate);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出体检报告模板列表
+     */
+    @PreAuthorize("@ss.hasPermi('his:physicalReportTemplate:export')")
+    @Log(title = "体检报告模板", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(FsPhysicalReportTemplate fsPhysicalReportTemplate)
+    {
+        List<FsPhysicalReportTemplate> list = fsPhysicalReportTemplateService.selectFsPhysicalReportTemplateList(fsPhysicalReportTemplate);
+        ExcelUtil<FsPhysicalReportTemplate> util = new ExcelUtil<FsPhysicalReportTemplate>(FsPhysicalReportTemplate.class);
+        return util.exportExcel(list, "体检报告模板数据");
+    }
+
+    /**
+     * 获取体检报告模板详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('his:physicalReportTemplate:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") String id)
+    {
+        return AjaxResult.success(fsPhysicalReportTemplateService.selectFsPhysicalReportTemplateById(id));
+    }
+
+    /**
+     * 新增体检报告模板
+     */
+    @PreAuthorize("@ss.hasPermi('his:physicalReportTemplate:add')")
+    @Log(title = "体检报告模板", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody FsPhysicalReportTemplate fsPhysicalReportTemplate)
+    {
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        fsPhysicalReportTemplate.setCreateBy(String.valueOf(loginUser.getUserId()));
+        return toAjax(fsPhysicalReportTemplateService.insertFsPhysicalReportTemplate(fsPhysicalReportTemplate));
+    }
+
+    /**
+     * 修改体检报告模板
+     */
+    @PreAuthorize("@ss.hasPermi('his:physicalReportTemplate:edit')")
+    @Log(title = "体检报告模板", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody FsPhysicalReportTemplate fsPhysicalReportTemplate)
+    {
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        fsPhysicalReportTemplate.setUpdateBy(String.valueOf(loginUser.getUserId()));
+        return toAjax(fsPhysicalReportTemplateService.updateFsPhysicalReportTemplate(fsPhysicalReportTemplate));
+    }
+
+    /**
+     * 删除体检报告模板
+     */
+    @PreAuthorize("@ss.hasPermi('his:physicalReportTemplate:remove')")
+    @Log(title = "体检报告模板", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable String[] ids)
+    {
+        return toAjax(fsPhysicalReportTemplateService.deleteFsPhysicalReportTemplateByIds(ids));
+    }
+}

+ 140 - 0
fs-admin/src/main/java/com/fs/his/controller/FsPhysicalReportTemplateFieldController.java

@@ -0,0 +1,140 @@
+package com.fs.his.controller;
+
+import java.util.List;
+
+import com.baomidou.mybatisplus.extension.api.R;
+import com.fs.common.core.domain.model.LoginUser;
+import com.fs.common.exception.ServiceException;
+import com.fs.common.utils.ServletUtils;
+import com.fs.common.utils.StringUtils;
+import com.fs.framework.web.service.TokenService;
+import com.fs.his.dto.FsPhysicalReportTemplateFieldDTO;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.fs.common.annotation.Log;
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.enums.BusinessType;
+import com.fs.his.domain.FsPhysicalReportTemplateField;
+import com.fs.his.service.IFsPhysicalReportTemplateFieldService;
+import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.common.core.page.TableDataInfo;
+
+/**
+ * 体检报告模板字段Controller
+ *
+ * @author fs
+ * @date 2025-07-24
+ */
+@RestController
+@RequestMapping("/his/physicalReportTemplateField")
+public class FsPhysicalReportTemplateFieldController extends BaseController {
+    @Autowired
+    private IFsPhysicalReportTemplateFieldService fsPhysicalReportTemplateFieldService;
+
+    @Autowired
+    private TokenService tokenService;
+
+    /**
+     * 查询体检报告模板字段列表
+     */
+    @PreAuthorize("@ss.hasPermi('his:physicalReportTemplateField:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(FsPhysicalReportTemplateField fsPhysicalReportTemplateField) {
+        startPage();
+        List<FsPhysicalReportTemplateField> list = fsPhysicalReportTemplateFieldService.selectFsPhysicalReportTemplateFieldList(fsPhysicalReportTemplateField);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出体检报告模板字段列表
+     */
+    @PreAuthorize("@ss.hasPermi('his:physicalReportTemplateField:export')")
+    @Log(title = "体检报告模板字段", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(FsPhysicalReportTemplateField fsPhysicalReportTemplateField) {
+        List<FsPhysicalReportTemplateField> list = fsPhysicalReportTemplateFieldService.selectFsPhysicalReportTemplateFieldList(fsPhysicalReportTemplateField);
+        ExcelUtil<FsPhysicalReportTemplateField> util = new ExcelUtil<FsPhysicalReportTemplateField>(FsPhysicalReportTemplateField.class);
+        return util.exportExcel(list, "体检报告模板字段数据");
+    }
+
+    /**
+     * 获取体检报告模板字段详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('his:physicalReportTemplateField:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") String id) {
+        return AjaxResult.success(fsPhysicalReportTemplateFieldService.selectFsPhysicalReportTemplateFieldById(id));
+    }
+
+    /**
+     * 新增体检报告模板字段
+     */
+    @PreAuthorize("@ss.hasPermi('his:physicalReportTemplateField:add')")
+    @Log(title = "体检报告模板字段", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody FsPhysicalReportTemplateField fsPhysicalReportTemplateField) {
+        return toAjax(fsPhysicalReportTemplateFieldService.insertFsPhysicalReportTemplateField(fsPhysicalReportTemplateField));
+    }
+
+    /**
+     * 修改体检报告模板字段
+     */
+    @PreAuthorize("@ss.hasPermi('his:physicalReportTemplateField:edit')")
+    @Log(title = "体检报告模板字段", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody FsPhysicalReportTemplateField fsPhysicalReportTemplateField) {
+        return toAjax(fsPhysicalReportTemplateFieldService.updateFsPhysicalReportTemplateField(fsPhysicalReportTemplateField));
+    }
+
+    /**
+     * 删除体检报告模板字段
+     */
+    @PreAuthorize("@ss.hasPermi('his:physicalReportTemplateField:remove')")
+    @Log(title = "体检报告模板字段", businessType = BusinessType.DELETE)
+    @DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable String[] ids) {
+        return toAjax(fsPhysicalReportTemplateFieldService.deleteFsPhysicalReportTemplateFieldByIds(ids));
+    }
+
+    /**
+     * 获取模板自定义字段
+     *
+     * @param templateId 模板ID
+     * @return R
+     **/
+    @PostMapping("/getTemplateField/{templateId}")
+    public R getTemplateField(@PathVariable String templateId) {
+        if (StringUtils.isNull(templateId)) {
+            return R.failed("操作失败,模板ID不能为空!");
+        }
+        return fsPhysicalReportTemplateFieldService.getTemplateField(templateId);
+    }
+
+    /**
+     * 新增模板
+     *
+     * @param fieldDTO
+     * @return AjaxResult
+     **/
+    @Log(title = "体检报告模板字段", businessType = BusinessType.INSERT)
+    @PostMapping("/saveTemplate")
+    public AjaxResult saveTemplate(@RequestBody FsPhysicalReportTemplateFieldDTO fieldDTO) {
+        if (StringUtils.isNull(fieldDTO.getTemplateId())) {
+            throw new ServiceException("操作失败,模板ID不能为空!");
+        } else if (fieldDTO.getTemplateFieldList().isEmpty()) {
+            throw new ServiceException("操作失败,字段列表不能为空!");
+        }
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        fieldDTO.setCreateBy(String.valueOf(loginUser.getUserId()));
+        return toAjax(fsPhysicalReportTemplateFieldService.saveFsPhysicalReportTemplateField(fieldDTO));
+    }
+}

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

@@ -102,6 +102,10 @@ public class FsStoreOrderController extends BaseController
     @Qualifier("dfOrderServiceImpl")
     private IErpOrderService dfOrderService;
 
+    @Autowired
+    @Qualifier("JSTErpOrderServiceImpl")
+    private IErpOrderService jSTOrderService;
+
     @Autowired
     SysConfigMapper sysConfigMapper;
 
@@ -413,6 +417,8 @@ public class FsStoreOrderController extends BaseController
                 } else if (erpType == 4){
                     //代服
                     erpOrderService =  dfOrderService;
+                }else if(erpType == 5){
+                    erpOrderService=jSTOrderService;
                 }
                 return erpOrderService;
 

+ 7 - 1
fs-admin/src/main/java/com/fs/his/task/Task.java

@@ -266,7 +266,7 @@ public class Task {
         List<FsStoreOrder> orders = null;
         if (erpOrderService == gyOrderService){
             orders = fsStoreOrderMapper.selectOmsOrderdeliveryOp();
-        } else if (erpOrderService == wdtOrderService || erpOrderService == dfOrderService){
+        } else if (erpOrderService == wdtOrderService || erpOrderService == dfOrderService || erpOrderService == jSTOrderService){
             orders = fsStoreOrderMapper.selectWdtOmsOrderdeliveryOp();
         }
 
@@ -1030,6 +1030,10 @@ public class Task {
     @Qualifier("dfOrderServiceImpl")
     private IErpOrderService dfOrderService;
 
+    @Autowired
+    @Qualifier("JSTErpOrderServiceImpl")
+    private IErpOrderService jSTOrderService;
+
     private IErpOrderService getErpService() {
         FsSysConfig sysConfig = configUtil.getSysConfig();
         Integer erpOpen = sysConfig.getErpOpen();
@@ -1050,6 +1054,8 @@ public class Task {
                 } else if (erpType == 4){
                     //代服
                     erpOrderService =  dfOrderService;
+                }else if(erpType == 5){
+                    erpOrderService=jSTOrderService;
                 }
                 return erpOrderService;
 

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

@@ -3,6 +3,7 @@ package com.fs.qw.qwTask;
 import com.fs.course.service.IFsUserCourseService;
 import com.fs.qw.service.IQwExternalContactService;
 import com.fs.qw.service.IQwGroupMsgService;
+import com.fs.qw.service.IQwMaterialService;
 import com.fs.qw.service.IQwUserService;
 import com.fs.sop.service.impl.QwSopLogsServiceImpl;
 import com.fs.sop.service.impl.QwSopServiceImpl;
@@ -46,6 +47,10 @@ public class qwTask {
     @Autowired
     private IFsStatisQwWatchService fsStatisQwWatchService;
 
+    @Autowired
+    private IQwMaterialService iQwMaterialService;
+
+
     //正在使用
     public void qwExternalContact()
     {
@@ -188,4 +193,10 @@ public class qwTask {
         fsStatisQwWatchService.writeData(today.toString());
     }
 
+    /**
+    * 每俩天 更新一次 素材库
+    */
+    public void updateMaterialByTwoDays(){
+        iQwMaterialService.updateQwMaterialByQw();
+    }
 }

+ 67 - 0
fs-company-app/src/main/java/com/fs/app/controller/FsUserCoursePeriodController.java

@@ -0,0 +1,67 @@
+package com.fs.app.controller;
+
+import com.fs.common.annotation.Log;
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.core.domain.R;
+import com.fs.common.core.page.TableDataInfo;
+import com.fs.common.enums.BusinessType;
+import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.course.domain.FsUserCoursePeriod;
+import com.fs.course.domain.FsUserCoursePeriodDays;
+import com.fs.course.domain.FsUserCourseVideoRedPackage;
+import com.fs.course.param.CompanyRedPacketParam;
+import com.fs.course.param.FsBatchPeriodRedPackageParam;
+import com.fs.course.param.PeriodCountParam;
+import com.fs.course.param.PeriodStatisticCountParam;
+import com.fs.course.service.IFsUserCoursePeriodDaysService;
+import com.fs.course.service.IFsUserCoursePeriodService;
+import com.fs.course.service.IFsUserCourseVideoRedPackageService;
+import com.fs.course.vo.FsPeriodCountVO;
+import com.fs.course.vo.FsUserCoursePeriodVO;
+import com.fs.course.vo.PeriodRedPacketVO;
+import com.fs.course.vo.UpdateCourseTimeVo;
+import com.fs.his.vo.OptionsVO;
+import com.github.pagehelper.PageHelper;
+import com.github.pagehelper.PageInfo;
+import io.swagger.annotations.ApiOperation;
+import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+
+/**
+ * 会员营期Controller
+ *
+ * @author fs
+ * @date 2025-04-11
+ */
+@RestController
+@AllArgsConstructor
+@RequestMapping("/course/period")
+@Slf4j
+public class FsUserCoursePeriodController extends BaseController {
+
+    private final IFsUserCoursePeriodService fsUserCoursePeriodService;
+
+    @PostMapping("/periodCourseStatisticCount")
+    @ApiOperation("会员详情训练营数据总览")
+    public R periodCourseStatisticCount(@RequestBody PeriodStatisticCountParam param) {
+        if (param == null) {
+            return R.error("请求参数不能为空!");
+        }
+        return R.ok().put("data", fsUserCoursePeriodService.periodCourseStatisticCount(param));
+    }
+
+    @PostMapping("/periodlist")
+    public R periodList(@RequestBody PeriodStatisticCountParam param)
+    {
+        List<FsUserCoursePeriod> list = fsUserCoursePeriodService.selectFsPeriodlist(param);
+        return R.ok().put("data", list);
+    }
+}

+ 46 - 0
fs-company-app/src/main/java/com/fs/app/controller/qw/QwFsCourseWatchLogController.java

@@ -0,0 +1,46 @@
+package com.fs.app.controller.qw;
+
+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.exception.CustomException;
+import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.course.domain.FsCourseWatchLog;
+import com.fs.course.param.FsCourseWatchLogListParam;
+import com.fs.course.param.FsCourseWatchLogStatisticsListParam;
+import com.fs.course.param.PeriodStatisticCountParam;
+import com.fs.course.service.IFsCourseWatchLogService;
+import com.fs.course.vo.FsCourseWatchLogListVO;
+import com.fs.course.vo.FsCourseWatchLogStatisticsListVO;
+import com.fs.qw.param.QwWatchLogStatisticsListParam;
+import com.fs.qw.service.IQwWatchLogService;
+import com.fs.qw.vo.QwWatchLogAllStatisticsListVO;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 短链课程看课记录Controller
+ *
+ * @author fs
+ * @date 2024-10-24
+ */
+@RestController
+@RequestMapping("/qw/course/courseWatchLog")
+public class QwFsCourseWatchLogController extends BaseController {
+    @Autowired
+    private IFsCourseWatchLogService fsCourseWatchLogService;
+
+    //    @PreAuthorize("@ss.hasPermi('course:courseWatchLog:list')")
+    @GetMapping("/listBytrainingCampId")
+    public TableDataInfo listBytrainingCampId(PeriodStatisticCountParam param) {
+        startPage();
+        List<FsCourseWatchLogListVO> list = fsCourseWatchLogService.selectListBytrainingCampId(param);
+        return getDataTable(list);
+    }
+}

+ 2 - 0
fs-company/src/main/java/com/fs/company/controller/qw/QwMaterialController.java

@@ -1,6 +1,7 @@
 package com.fs.company.controller.qw;
 
 import com.fs.common.annotation.Log;
+import com.fs.common.annotation.RepeatSubmit;
 import com.fs.common.core.controller.BaseController;
 import com.fs.common.core.domain.AjaxResult;
 import com.fs.common.core.domain.R;
@@ -101,6 +102,7 @@ public class QwMaterialController extends BaseController
     @PreAuthorize("@ss.hasPermi('qw:material:add')")
     @Log(title = "素材库", businessType = BusinessType.INSERT)
     @PostMapping
+    @RepeatSubmit
     public R add(@RequestBody QwMaterial qwMaterial) throws Exception {
         LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
         qwMaterial.setCreateUserId(loginUser.getUser().getUserId());

+ 4 - 5
fs-company/src/main/java/com/fs/company/controller/qw/SopUserLogsInfoController.java

@@ -26,14 +26,11 @@ import com.fs.sop.params.SendUserLogsInfoMsgParam;
 import com.fs.sop.service.ISopUserLogsInfoService;
 import com.fs.voice.utils.StringUtil;
 import com.google.gson.Gson;
-import com.google.gson.JsonSyntaxException;
 import com.google.gson.reflect.TypeToken;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.web.bind.annotation.*;
 
-import java.io.IOException;
-import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.time.format.DateTimeFormatter;
 import java.util.*;
@@ -98,8 +95,10 @@ public class SopUserLogsInfoController extends BaseController
                     Map<String, QwTag> tagMap = PubFun.listToMapByGroupObject(tagList, QwTag::getTagId);
                     qwExternalContactVOTimes.forEach(e -> {
                         List<String> tagId = JSON.parseArray(e.getTagIds(), String.class);
-                        List<String> tagNameList = tagId.stream().filter(tagMap::containsKey).map(t -> tagMap.get(t).getName()).filter(StringUtils::isNotEmpty).collect(Collectors.toList());
-                        e.setTagIdsName(tagNameList);
+                        if(StringUtils.isNotEmpty(tagId)){
+                            List<String> tagNameList = tagId.stream().filter(tagMap::containsKey).map(t -> tagMap.get(t).getName()).filter(StringUtils::isNotEmpty).collect(Collectors.toList());
+                            e.setTagIdsName(tagNameList);
+                        }
                     });
                 }
                 // 设置联系信息

+ 7 - 0
fs-company/src/main/java/com/fs/company/controller/store/FsStoreOrderController.java

@@ -527,6 +527,11 @@ public class FsStoreOrderController extends BaseController
     @Autowired
     @Qualifier("wdtErpOrderServiceImpl")
     private IErpOrderService wdtOrderService;
+
+    @Autowired
+    @Qualifier("JSTErpOrderServiceImpl")
+    private IErpOrderService jSTOrderService;
+
     private IErpOrderService getErpService() {
         FsSysConfig sysConfig = configUtil.getSysConfig();
         Integer erpOpen = sysConfig.getErpOpen();
@@ -541,6 +546,8 @@ public class FsStoreOrderController extends BaseController
                 } else if (erpType == 2){
                     //旺店通
                     erpOrderService =  wdtOrderService;
+                }else if(erpType == 5){
+                    erpOrderService = jSTOrderService;
                 }
                 return erpOrderService;
 

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

@@ -161,7 +161,7 @@ public class SendMsg {
             Long time = redisCache.getCacheObject(key);
             if (redisCache.getCacheObject(key) != null) {
                 log.error("{}已有发送:{}, :{}", qwUser.getQwUserName(), qwSopLogs.getId(), time);
-                return;
+                continue;
             }
             redisCache.setCacheObject(key, System.currentTimeMillis(), 10, TimeUnit.MINUTES);
             for (QwSopCourseFinishTempSetting.Setting content : setting.getSetting()) {

+ 5 - 3
fs-qw-task/src/main/java/com/fs/app/controller/CommonController.java

@@ -16,6 +16,7 @@ import com.fs.his.service.IFsInquiryOrderService;
 import com.fs.his.service.IFsPackageOrderService;
 import com.fs.qw.mapper.QwExternalContactMapper;
 import com.fs.qw.service.IQwExternalContactService;
+import com.fs.qw.service.IQwMaterialService;
 import com.fs.qwApi.service.QwApiService;
 import com.fs.sop.mapper.QwSopLogsMapper;
 import com.fs.sop.mapper.QwSopMapper;
@@ -99,6 +100,8 @@ public class CommonController {
     @Autowired
     private IFsInquiryOrderService inquiryOrderService;
 
+    @Autowired
+    private IQwMaterialService iQwMaterialService;
 
     /**
     * 发官方通连
@@ -139,9 +142,8 @@ public class CommonController {
     @GetMapping("/testSop")
     public R testSop() throws Exception {
 
-        byte[] bytes = inquiryOrderService.getWxaCodeInquiryOrderUnLimit(2582616L);
-        String base64 = Base64.getEncoder().encodeToString(bytes);
-        return R.ok().put("data",base64);
+        iQwMaterialService.updateQwMaterialByQw();
+        return R.ok();
     }
 
     @GetMapping("/testRatingSop")

+ 73 - 0
fs-qwhook-sop/src/main/java/com/fs/app/controller/ApisQwMaterialBySidebar.java

@@ -0,0 +1,73 @@
+package com.fs.app.controller;
+
+import com.fs.common.core.domain.R;
+import com.fs.qw.domain.QwUser;
+import com.fs.qw.param.QwMaterialParam;
+import com.fs.qw.param.QwMaterialParamBySidebar;
+import com.fs.qw.service.IQwExternalContactService;
+import com.fs.qw.service.IQwMaterialService;
+import com.fs.qw.vo.QwMaterialVO;
+import com.github.pagehelper.PageHelper;
+import com.github.pagehelper.PageInfo;
+import io.swagger.annotations.Api;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+@Api("素材库库相关接口")
+@RestController
+@RequestMapping("/apis/app/qw/material")
+@Slf4j
+public class ApisQwMaterialBySidebar {
+
+
+
+    @Autowired
+    private IQwExternalContactService qwExternalContactService;
+
+    @Autowired
+    private IQwMaterialService qwMaterialService;
+
+    /**
+     * 查询素材库列表
+     */
+    @PostMapping("/MaterialList")
+    public R list(@RequestBody QwMaterialParamBySidebar param)
+    {
+
+        QwUser qwUser = qwExternalContactService.getQwUserByRedis(param.getCorpId().trim(),param.getQwUserId().trim());
+
+        if (qwUser == null || qwUser.getCompanyId() == null) {
+            return R.error("员工未绑定 销售公司 或 未获取到员工信息,请重试!");
+        }
+
+
+        PageHelper.startPage(param.getPageNum(), param.getPageSize());
+
+        QwMaterialParam materialParam=new QwMaterialParam();
+        materialParam.setCompanyId(qwUser.getCompanyId());
+        materialParam.setTitle(param.getKeyword());
+        List<QwMaterialVO> list = qwMaterialService.selectQwMaterialList(materialParam);
+
+
+        PageInfo<QwMaterialVO> result = new PageInfo<>(list);
+        return R.ok().put("data", result);
+
+
+    }
+
+    @GetMapping("/updateMaterialTime/{materialId}")
+    public R updateMaterialTime(@PathVariable Long materialId) throws Exception {
+
+        return R.ok().put("data",qwMaterialService.selectQwMaterialByMaterialIdByTime(materialId));
+    }
+
+    @GetMapping("/getMaterialByTime/{materialId}")
+    public R getMaterialByTime(@PathVariable Long materialId) throws Exception {
+
+        return R.ok().put("data",qwMaterialService.selectQwMaterialByMaterialIdByTimeTwo(materialId));
+    }
+
+}

+ 72 - 0
fs-qwhook-sop/src/main/java/com/fs/app/controller/QwMaterialBySidebar.java

@@ -0,0 +1,72 @@
+package com.fs.app.controller;
+
+import com.fs.common.core.domain.R;
+import com.fs.qw.domain.QwUser;
+import com.fs.qw.param.QwMaterialParam;
+import com.fs.qw.param.QwMaterialParamBySidebar;
+import com.fs.qw.service.IQwExternalContactService;
+import com.fs.qw.service.IQwMaterialService;
+import com.fs.qw.vo.QwMaterialVO;
+import com.github.pagehelper.PageHelper;
+import com.github.pagehelper.PageInfo;
+import io.swagger.annotations.Api;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+@Api("素材库库相关接口")
+@RestController
+@RequestMapping("/app/qw/material")
+@Slf4j
+public class QwMaterialBySidebar {
+
+
+
+    @Autowired
+    private IQwExternalContactService qwExternalContactService;
+
+    @Autowired
+    private IQwMaterialService qwMaterialService;
+
+    /**
+     * 查询素材库列表
+     */
+    @PostMapping("/MaterialList")
+    public R list(@RequestBody QwMaterialParamBySidebar param)
+    {
+
+        QwUser qwUser = qwExternalContactService.getQwUserByRedis(param.getCorpId().trim(),param.getQwUserId().trim());
+
+        if (qwUser == null || qwUser.getCompanyId() == null) {
+            return R.error("员工未绑定 销售公司 或 未获取到员工信息,请重试!");
+        }
+
+
+        PageHelper.startPage(param.getPageNum(), param.getPageSize());
+
+        QwMaterialParam materialParam=new QwMaterialParam();
+        materialParam.setCompanyId(qwUser.getCompanyId());
+        materialParam.setTitle(param.getKeyword());
+        List<QwMaterialVO> list = qwMaterialService.selectQwMaterialList(materialParam);
+
+
+        PageInfo<QwMaterialVO> result = new PageInfo<>(list);
+        return R.ok().put("data", result);
+
+    }
+
+    @GetMapping("/updateMaterialTime/{materialId}")
+    public R updateMaterialTime(@PathVariable Long materialId) throws Exception {
+
+        return R.ok().put("data",qwMaterialService.selectQwMaterialByMaterialIdByTime(materialId));
+    }
+
+    @GetMapping("/getMaterialByTime/{materialId}")
+    public R getMaterialByTime(@PathVariable Long materialId) throws Exception {
+
+        return R.ok().put("data",qwMaterialService.selectQwMaterialByMaterialIdByTimeTwo(materialId));
+    }
+
+}

+ 81 - 0
fs-qwhook/src/main/java/com/fs/app/controller/ApisQwMaterialBySidebar.java

@@ -0,0 +1,81 @@
+package com.fs.app.controller;
+
+import com.fs.common.core.domain.R;
+import com.fs.qw.domain.QwMaterial;
+import com.fs.qw.domain.QwUser;
+import com.fs.qw.param.QwMaterialParam;
+import com.fs.qw.param.QwMaterialParamBySidebar;
+import com.fs.qw.service.IQwExternalContactService;
+import com.fs.qw.service.IQwMaterialService;
+import com.fs.qw.vo.QwMaterialVO;
+import com.github.pagehelper.PageHelper;
+import com.github.pagehelper.PageInfo;
+import io.swagger.annotations.Api;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+@Api("素材库库相关接口")
+@RestController
+@RequestMapping("/apis/app/qw/material")
+@Slf4j
+public class ApisQwMaterialBySidebar {
+
+
+
+    @Autowired
+    private IQwExternalContactService qwExternalContactService;
+
+    @Autowired
+    private IQwMaterialService qwMaterialService;
+
+    /**
+     * 查询素材库列表
+     */
+    @PostMapping("/MaterialList")
+    public R list(@RequestBody QwMaterialParamBySidebar param)
+    {
+
+        QwUser qwUser = qwExternalContactService.getQwUserByRedis(param.getCorpId().trim(),param.getQwUserId().trim());
+
+        if (qwUser == null || qwUser.getCompanyId() == null) {
+            return R.error("员工未绑定 销售公司 或 未获取到员工信息,请重试!");
+        }
+
+
+        PageHelper.startPage(param.getPageNum(), param.getPageSize());
+
+        QwMaterialParam materialParam=new QwMaterialParam();
+        materialParam.setCompanyId(qwUser.getCompanyId());
+        materialParam.setTitle(param.getKeyword());
+        List<QwMaterialVO> list = qwMaterialService.selectQwMaterialList(materialParam);
+
+
+        PageInfo<QwMaterialVO> result = new PageInfo<>(list);
+        return R.ok().put("data", result);
+
+
+    }
+
+    /**
+    * 更新 素材库的某个素材的 media_id
+    */
+    @GetMapping("/updateMaterialTime/{materialId}")
+    public R updateMaterialTime(@PathVariable Long materialId) throws Exception {
+
+        return R.ok().put("data",qwMaterialService.selectQwMaterialByMaterialIdByTime(materialId));
+    }
+
+    /**
+    * 获取某个素材id
+    */
+    @GetMapping("/getMaterialByTime/{materialId}")
+    public R getMaterialByTime(@PathVariable Long materialId) throws Exception {
+
+        return R.ok().put("data",qwMaterialService.selectQwMaterialByMaterialIdByTimeTwo(materialId));
+    }
+
+
+}

+ 73 - 0
fs-qwhook/src/main/java/com/fs/app/controller/QwMaterialBySidebar.java

@@ -0,0 +1,73 @@
+package com.fs.app.controller;
+
+import com.fs.common.core.domain.R;
+import com.fs.qw.domain.QwUser;
+import com.fs.qw.param.QwMaterialParam;
+import com.fs.qw.param.QwMaterialParamBySidebar;
+import com.fs.qw.service.IQwExternalContactService;
+import com.fs.qw.service.IQwMaterialService;
+import com.fs.qw.vo.QwMaterialVO;
+import com.github.pagehelper.PageHelper;
+import com.github.pagehelper.PageInfo;
+import io.swagger.annotations.Api;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+@Api("素材库库相关接口")
+@RestController
+@RequestMapping("/app/qw/material")
+@Slf4j
+public class QwMaterialBySidebar {
+
+
+
+    @Autowired
+    private IQwExternalContactService qwExternalContactService;
+
+    @Autowired
+    private IQwMaterialService qwMaterialService;
+
+    /**
+     * 查询素材库列表
+     */
+    @PostMapping("/MaterialList")
+    public R list(@RequestBody QwMaterialParamBySidebar param)
+    {
+
+        QwUser qwUser = qwExternalContactService.getQwUserByRedis(param.getCorpId().trim(),param.getQwUserId().trim());
+
+        if (qwUser == null || qwUser.getCompanyId() == null) {
+            return R.error("员工未绑定 销售公司 或 未获取到员工信息,请重试!");
+        }
+
+
+        PageHelper.startPage(param.getPageNum(), param.getPageSize());
+
+        QwMaterialParam materialParam=new QwMaterialParam();
+        materialParam.setCompanyId(qwUser.getCompanyId());
+        materialParam.setTitle(param.getKeyword());
+        List<QwMaterialVO> list = qwMaterialService.selectQwMaterialList(materialParam);
+
+
+        PageInfo<QwMaterialVO> result = new PageInfo<>(list);
+        return R.ok().put("data", result);
+
+
+    }
+
+    @GetMapping("/updateMaterialTime/{materialId}")
+    public R updateMaterialTime(@PathVariable Long materialId) throws Exception {
+
+        return R.ok().put("data",qwMaterialService.selectQwMaterialByMaterialIdByTime(materialId));
+    }
+
+    @GetMapping("/getMaterialByTime/{materialId}")
+    public R getMaterialByTime(@PathVariable Long materialId) throws Exception {
+
+        return R.ok().put("data",qwMaterialService.selectQwMaterialByMaterialIdByTimeTwo(materialId));
+    }
+
+}

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

@@ -13,7 +13,7 @@ import com.fs.his.vo.OptionsVO;
 import java.util.List;
 import java.util.Map;
 
-/**
+    /**
  * 营期课程Service接口
  *
  * @author fs

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

@@ -1,6 +1,7 @@
 package com.fs.course.service.impl;
 
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.fs.common.core.domain.R;
 import com.fs.common.utils.DateUtils;
@@ -24,6 +25,8 @@ import com.fs.course.vo.UpdateCourseTimeVo;
 import com.fs.course.vo.newfs.FsCourseAnalysisCountVO;
 import com.fs.his.mapper.FsUserMapper;
 import com.fs.his.vo.OptionsVO;
+import com.fs.system.domain.SysConfig;
+import com.fs.system.mapper.SysConfigMapper;
 import lombok.AllArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.BeanUtils;
@@ -54,6 +57,7 @@ public class FsUserCoursePeriodDaysServiceImpl extends ServiceImpl<FsUserCourseP
     private final FsUserCoursePeriodMapper fsUserCoursePeriodMapper;
 
     private final FsUserMapper fsUserMapper;
+    private final SysConfigMapper sysConfigMapper;
 
     private final FsUserCoursePeriodDaysMapper fsUserCoursePeriodDaysMapper;
     private final IFsUserCourseVideoService fsUserCourseVideoService;
@@ -178,6 +182,10 @@ public class FsUserCoursePeriodDaysServiceImpl extends ServiceImpl<FsUserCourseP
             }else if(video.getViewEndTime() != null){
                 day.setEndDateTime(LocalDateTime.of(day.getDayDate(), video.getViewEndTime()));
             }
+            SysConfig config = sysConfigMapper.selectConfigByConfigKey("joinTime.switch.config");
+            if (ObjectUtils.isNotEmpty(config)&&config.getConfigValue().equals("1")){
+                entity.setJoinTime(entity.getEndTime1());
+            }
             if(entity.getJoinTime() != null){
                 day.setLastJoinTime(LocalDateTime.of(day.getDayDate(), entity.getJoinTime()));
             }else if(video.getLastJoinTime() != null){
@@ -339,7 +347,14 @@ public class FsUserCoursePeriodDaysServiceImpl extends ServiceImpl<FsUserCourseP
             // 调整时间为直接接收前端传入的年月日,不使用营期的日期(2025年6月11日 10点41分)
             day.setStartDateTime(vo.getStartTime());
             day.setEndDateTime(vo.getEndTime1());
-            day.setLastJoinTime(vo.getJoinTime());
+
+            SysConfig config = sysConfigMapper.selectConfigByConfigKey("joinTime.switch.config");
+            if (ObjectUtils.isNotEmpty(config)&&config.getConfigValue().equals("1")){
+                day.setLastJoinTime(vo.getEndTime1());
+            }else {
+                day.setLastJoinTime(vo.getJoinTime());
+            }
+
             // 把营期时间改成开始时间
             day.setDayDate(vo.getStartTime().toLocalDate());
             // 设置状态

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

@@ -861,6 +861,9 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
 //        if (StringUtils.isEmpty(user.getMpOpenId())){
 //            return R.error("未识别到领取信息");
 //        }
+        if (user.getStatus()==0){
+            return R.error("会员被停用,无权限,请联系客服!");
+        }
         FsCourseWatchLog log = new FsCourseWatchLog();
 
         // 根据链接类型判断是否已发放奖励

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

@@ -21,4 +21,7 @@ public class ErpGoods {
     List<ErpCombineItem> combine_item;
     //hzOMSErp 使用 商品id
     Long storeProductId;
+
+    //适用多商品批量上传
+    List<Long> productIdList;
 }

+ 10 - 0
fs-service/src/main/java/com/fs/erp/dto/OrderItemDTO.java

@@ -55,4 +55,14 @@ public class OrderItemDTO implements Serializable {
      * 生产日期
      */
     private String producedDate;
+
+    /**
+     * 商品属性
+     * **/
+    private String propertiesValue;
+
+    /**
+     * 款式编码
+     * **/
+    private String shopIId;
 }

+ 2 - 1
fs-service/src/main/java/com/fs/erp/http/JstErpHttpService.java

@@ -1,5 +1,6 @@
 package com.fs.erp.http;
 
+import com.alibaba.fastjson.JSONObject;
 import com.fs.erp.dto.*;
 import com.fs.ybPay.dto.RefundOrderDTO;
 
@@ -32,7 +33,7 @@ public interface JstErpHttpService {
      * @param dto 请求参数
      * @return ProductUploadResultDTO
      */
-    ProductUploadResultDTO uploadGoods(GoodsInfoDTO dto);
+    ProductUploadResultDTO uploadGoods(JSONObject dto);
 
     /**
      * 普通商品资料查询(按sku查询)

+ 14 - 1
fs-service/src/main/java/com/fs/erp/http/JstErpHttpServiceImpl.java

@@ -5,6 +5,7 @@ import cn.hutool.core.map.MapUtil;
 import cn.hutool.http.HttpRequest;
 import cn.hutool.http.HttpResponse;
 import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
 import com.alibaba.fastjson.PropertyNamingStrategy;
 import com.alibaba.fastjson.TypeReference;
 import com.alibaba.fastjson.serializer.SerializeConfig;
@@ -27,6 +28,7 @@ import java.util.Map;
 @Service
 public class JstErpHttpServiceImpl implements JstErpHttpService {
 
+    //正式
     private static final String BASE_URL = "https://openapi.jushuitan.com/";
     /**
      * 获取access_token、refresh_token url
@@ -38,6 +40,17 @@ public class JstErpHttpServiceImpl implements JstErpHttpService {
      */
     private static final String REFRESH_TOKEN_URL = BASE_URL + "openWeb/auth/refreshToken";
 
+    //测试
+//    private static final String BASE_URL = "https://dev-api.jushuitan.com/";
+//    /**
+//     * 获取access_token、refresh_token url
+//     */
+//    private static final String GET_INIT_TOKEN_URL = BASE_URL + "openWebIsv/auth/getInitToken";
+//
+//    /**
+//     * 更新access_token、refresh_token url
+//     */
+//    private static final String REFRESH_TOKEN_URL = BASE_URL + "openWebIsv/auth/refreshToken;
 
     @Value("${jst.app_key:''}")
     private String appKey;
@@ -68,7 +81,7 @@ public class JstErpHttpServiceImpl implements JstErpHttpService {
     }
 
     @Override
-    public ProductUploadResultDTO uploadGoods(GoodsInfoDTO dto) {
+    public ProductUploadResultDTO uploadGoods(JSONObject dto) {
         String url = BASE_URL + "/open/jushuitan/itemsku/upload";
         log.info("上传商品信息 - URL: {}, 请求体: {}", url, JSON.toJSONString(dto));
 

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

@@ -1,22 +1,54 @@
 package com.fs.erp.service.impl;
 
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.fs.common.utils.StringUtils;
 import com.fs.erp.domain.ErpGoods;
 import com.fs.erp.dto.*;
 import com.fs.erp.http.JstErpHttpService;
 import com.fs.erp.service.IErpGoodsService;
+import com.fs.his.domain.FsStoreProduct;
+import com.fs.his.domain.FsStoreProductAttrValue;
+import com.fs.his.service.IFsStoreProductAttrValueService;
+import com.fs.his.service.IFsStoreProductService;
+import com.fs.voice.utils.StringUtil;
 import org.apache.commons.collections4.CollectionUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.stream.Collectors;
 
 @Service("JSTErpGoodsServiceImpl")
 public class JSTErpGoodsServiceImpl implements IErpGoodsService {
     @Autowired
     private JstErpHttpService jstErpHttpService;
+
+    @Autowired
+    private IFsStoreProductService fsStoreProductService;
+
+    @Autowired
+    private IFsStoreProductAttrValueService fsStoreProductAttrValueService;
+
+    // 每次最大处理数量
+    private static final int BATCH_SIZE = 190;
+
     @Override
     public BaseResponse addGoods(ErpGoods goods) {
+        List<Long> storeProductIds = goods.getProductIdList();
+        JSONArray bulidJSONArray = buildGoods(storeProductIds);
+
+        //调用接口
+        for (int i = 0; i < bulidJSONArray.size(); i += BATCH_SIZE) {
+            JSONObject request=new JSONObject();
+            int end = Math.min(i + BATCH_SIZE, bulidJSONArray.size());
+            request.put("items",bulidJSONArray.subList(i, end));
+            jstErpHttpService.uploadGoods(request);
+        }
+
         return null;
     }
 
@@ -27,7 +59,7 @@ public class JSTErpGoodsServiceImpl implements IErpGoodsService {
         ProductResponseDTO productResponseDTO = jstErpHttpService.queryGoods(requestDTO);
         List<ProductResponseDTO.ProductInfo> datas = productResponseDTO.getDatas();
         ErpGoodsQueryResponse erpGoodsQueryResponse = new ErpGoodsQueryResponse();
-        if(CollectionUtils.isNotEmpty(datas)){
+        if (CollectionUtils.isNotEmpty(datas)) {
             List<ErpGoods> erpGoodsList = new ArrayList<>();
             for (ProductResponseDTO.ProductInfo data : datas) {
                 ErpGoods erpGoods = new ErpGoods();
@@ -49,4 +81,46 @@ public class JSTErpGoodsServiceImpl implements IErpGoodsService {
     public ErpGoodsStockQueryResponse getGoodsStock(ErpGoodsStockQueryRequert param) {
         return null;
     }
+
+    /**
+     * 构建店铺商品上传的参数
+     *
+     * @param storeProductIds
+     * @return
+     */
+    public JSONArray buildGoods(List<Long> storeProductIds) {
+        JSONArray res = new JSONArray();
+        //商品
+        List<FsStoreProduct> fsStoreProductList = fsStoreProductService.getStoreProductInProductIds(storeProductIds);
+        if (!fsStoreProductList.isEmpty()) {
+
+            Map<Long, FsStoreProduct> productMap = fsStoreProductList.stream().collect(Collectors.toMap(FsStoreProduct::getProductId, p -> p));
+            //商品规格List
+            List<FsStoreProductAttrValue> fsStoreProductAttrValues = fsStoreProductAttrValueService.getFsStoreProductAttrValueListInProductId(storeProductIds);
+
+            //按规格构建商品数据
+            fsStoreProductAttrValues.forEach(v -> {
+                JSONObject productJson = new JSONObject();
+                FsStoreProduct product = productMap.get(v.getProductId());
+                productJson.put("sku_id", v.getBarCode());//商品编码
+                productJson.put("i_id", v.getBarCode());//如果没有款式默认商品编码一致
+                productJson.put("name", v.getSku());//名称
+                productJson.put("short_name", product.getKeyword());//简称
+                if(StringUtils.isNotEmpty(product.getBrand())){
+                    productJson.put("brand", product.getBrand());//品牌
+                }
+                productJson.put("weight", v.getWeight());//重量
+                productJson.put("s_price",v.getPrice());//基本售价
+                productJson.put("c_price", v.getCost());//成本
+                productJson.put("market_price", v.getOtPrice());//市场|吊牌价
+                productJson.put("unit", product.getUnitName());//单位
+                productJson.put("sku_pic", v.getImage());//商品图片
+                productJson.put("pic", v.getImage());//图片地址(款图片)
+                productJson.put("pic_big", v.getImage());//大图地址
+                res.add(productJson);
+            });
+        }
+
+        return res;
+    }
 }

+ 3 - 0
fs-service/src/main/java/com/fs/erp/service/impl/JSTErpOrderServiceImpl.java

@@ -135,10 +135,13 @@ public class JSTErpOrderServiceImpl implements IErpOrderService {
 
             String barCode = jsonObject.getString("barCode");
             String productName = jsonObject.getString("productName");
+            String sku=jsonObject.getString("sku");
 
             orderItemDTO.setSkuId(barCode);
             orderItemDTO.setShopSkuId(barCode);
             orderItemDTO.setName(productName);
+            orderItemDTO.setShopIId(orderItemDTO.getSkuId());//款式编码ID,当前没有这个目前就与SKU ID一致
+            orderItemDTO.setPropertiesValue(sku);//商品属性
 
             FsStoreProduct fsStoreProduct = fsStoreProductService.selectFsStoreProductById(item.getProductId());
 

+ 22 - 2
fs-service/src/main/java/com/fs/erp/service/impl/JstTokenService.java

@@ -6,6 +6,8 @@ import com.fs.erp.dto.GetInitTokenResponseDTO;
 import com.fs.erp.dto.RefreshTokenRequestDTO;
 import com.fs.erp.http.JstErpHttpService;
 import com.fs.erp.utils.SignUtil;
+import com.fs.his.config.FsSysConfig;
+import com.fs.his.utils.ConfigUtil;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -40,6 +42,9 @@ public class JstTokenService {
     @Autowired
     private StringRedisTemplate redisTemplate;
 
+    @Autowired
+    private ConfigUtil configUtil;
+
     /**
      * 获取访问令牌,如果缓存中存在有效令牌则直接返回,否则重新获取
      * @return 有效的访问令牌
@@ -159,14 +164,29 @@ public class JstTokenService {
     }
 
     /**
-     * 定时任务,每20天刷新一次令牌
+     * 定时任务,每28天凌晨3点刷新一次令牌
      * 根据文档说明,刷新token必须在有效期小于15天时进行,所以这里设置20天刷新一次
      */
 //    @Scheduled(fixedRate = 20 * 24 * 60 * 60 * 1000)
+    @Scheduled(cron = "0 0 3 */28 * ?")
     public void scheduleTokenRefresh() {
         log.info("定时任务:刷新聚水潭API令牌");
         try {
-            refreshAccessToken();
+            //判断是否开启erp
+            FsSysConfig sysConfig = configUtil.getSysConfig();
+            Integer erpOpen = sysConfig.getErpOpen();
+            if (erpOpen == null || erpOpen == 0) {
+                return;
+            }
+
+            //判断erp类型
+            Integer erpType = sysConfig.getErpType();
+            if (erpType == null) {
+                return;
+            } else if (erpType == 5){
+                //聚水潭
+                refreshAccessToken();
+            }
         } catch (Exception e) {
             log.error("定时刷新令牌失败", e);
         }

+ 32 - 0
fs-service/src/main/java/com/fs/his/domain/FsPhysicalReportTemplate.java

@@ -0,0 +1,32 @@
+package com.fs.his.domain;
+
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.fs.common.annotation.Excel;
+import lombok.Data;
+import com.fs.common.core.domain.BaseEntity;
+import lombok.EqualsAndHashCode;
+
+/**
+ * 体检报告模板对象 fs_physical_report_template
+ *
+ * @author fs
+ * @date 2025-07-23
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class FsPhysicalReportTemplate extends BaseEntity{
+
+    /** 体检模板ID */
+    @Excel(name = "模板编码")
+    private Long id;
+
+    /** 体检模板名称 */
+    @Excel(name = "模板名称")
+    private String templateName;
+
+    /** 状态(0未启用、1启用) */
+    @Excel(name = "状态", readConverterExp = "0=未启用、1启用")
+    private String status;
+
+
+}

+ 72 - 0
fs-service/src/main/java/com/fs/his/domain/FsPhysicalReportTemplateField.java

@@ -0,0 +1,72 @@
+package com.fs.his.domain;
+
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.fs.common.annotation.Excel;
+import lombok.Data;
+import com.fs.common.core.domain.BaseEntity;
+import lombok.EqualsAndHashCode;
+
+/**
+ * 体检报告模板字段对象 fs_physical_report_template_field
+ *
+ * @author fs
+ * @date 2025-07-24
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class FsPhysicalReportTemplateField extends BaseEntity{
+
+    /** 字段id */
+    private String id;
+
+    /** 模板ID */
+    @Excel(name = "模板ID")
+    private Long templateId;
+
+    /** 组件ID,后续可联动组件 */
+    @Excel(name = "组件ID,后续可联动组件")
+    private Long componentId;
+
+    /** 字段组件名称 */
+    @Excel(name = "字段组件名称")
+    private String label;
+
+    /** 字段类型 */
+    @Excel(name = "字段类型")
+    private String type;
+
+    /** 排序 */
+    @Excel(name = "排序")
+    private Integer sort;
+
+    /** 是否必填0否1是 */
+    @Excel(name = "是否必填0否1是")
+    private Integer required;
+
+    /** 是否多选0否1是 */
+    @Excel(name = "是否多选0否1是")
+    private Integer multiple;
+
+    /** 多选下来数据 */
+    @Excel(name = "多选下来数据")
+    private String multiples;
+
+    /** 输入框最大长度 */
+    @Excel(name = "输入框最大长度")
+    private Long maxLength;
+
+    /** 输入框最小长度 */
+    @Excel(name = "输入框最小长度")
+    private Long minLength;
+
+    /** 状态(1未启用、2启用) */
+    @Excel(name = "状态", readConverterExp = "1=未启用、2启用")
+    private Long status;
+
+    /**
+     * 下拉多选,复选框多选值
+     * **/
+    private String options;
+
+
+}

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

@@ -229,6 +229,10 @@ public class FsStoreProduct extends BaseEntity {
     @Excel(name = "是否在商品展示")
     private Integer isDisplay;
 
+    /** 品牌 */
+    @Excel(name = "品牌")
+    private String brand;
+
     /**
      * 运费模板
      */

+ 19 - 0
fs-service/src/main/java/com/fs/his/dto/FsPhysicalReportTemplateFieldDTO.java

@@ -0,0 +1,19 @@
+package com.fs.his.dto;
+
+import com.fs.his.domain.FsPhysicalReportTemplateField;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.List;
+
+@Data
+public class FsPhysicalReportTemplateFieldDTO implements Serializable {
+    //模板ID
+    private Long templateId;
+
+    //自定义字段类型
+    private List<FsPhysicalReportTemplateField> templateFieldList;
+
+    //创建人
+    private String createBy;
+}

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

@@ -102,19 +102,25 @@ public interface FsInquiryOrderReportMapper
 
     @Select("select ior.*,u.nick_name,u.phone,d.doctor_name,su.nick_name user_name,send.nick_name send_name,fio.status inquiry_status,fio. inquiry_sub_type,fio.company_user_remark FROM fs_inquiry_order_report ior  LEFT JOIN fs_user u ON u.user_id=ior.user_id LEFT JOIN fs_doctor d ON d.doctor_id=ior.doctor_id LEFT JOIN sys_user su ON su.user_id=ior.audit_user_id LEFT JOIN fs_inquiry_order fio ON fio.order_id=ior.order_id LEFT JOIN fs_user_coupon fuc ON fuc.business_type =1 AND fuc.business_id=ior.order_id LEFT JOIN sys_user send ON send.user_id=fuc.send_user_id  where ior.report_id=#{reportId}")
     FsInquiryOrderReportVO selectFsInquiryOrderReportByReportIdVO(Long reportId);
+
     @Select("select report_id FROM fs_inquiry_order_report WHERE order_id=#{id}")
     Integer selectFsInquiryOrderReportIdByOrderId(Long id);
+
     @Select("select * FROM fs_inquiry_order_report   where order_id=#{orderId}")
     FsInquiryOrderReport selectFsInquiryOrderReportByOrderId(Long orderId);
+
     @Select("select o.*,d.dept_id FROM fs_inquiry_order_report o  LEFT JOIN fs_doctor d ON d.doctor_id=o.doctor_id   where o.order_id=#{orderId}")
     FsInquiryOrderReportUVO selectFsInquiryOrderReportUVOByOrderId(Long orderId);
+
     @Select("select item_type_json FROM fs_test_temp WHERE temp_code ='C1694077002122'")
     String selectFsTestBody();
 
     @Select("select * from fs_inquiry_order_report where patient_json LIKE '%https://htj-1258038825.cos.ap-beijing.myqcloud.com%' order by report_id desc limit 2 ")
     List<FsInquiryOrderReport> selectFsInquiryOrderReportListByUpdate();
+
     @Select("select ior.*,u.nick_name,u.phone,d.doctor_name,su.nick_name user_name,send.nick_name send_name,fio.status inquiry_status,fio. inquiry_sub_type,fio.company_user_remark FROM fs_inquiry_order_report ior  LEFT JOIN fs_user u ON u.user_id=ior.user_id LEFT JOIN fs_doctor d ON d.doctor_id=ior.doctor_id LEFT JOIN sys_user su ON su.user_id=ior.audit_user_id LEFT JOIN fs_inquiry_order fio ON fio.order_id=ior.order_id LEFT JOIN fs_user_coupon fuc ON fuc.business_type =1 AND fuc.business_id=ior.order_id LEFT JOIN sys_user send ON send.user_id=fuc.send_user_id  where ior.order_id=#{orderId} limit 1")
     FsInquiryOrderReportVO selectFsInquiryOrderReportByOrderIdVO(Long orderId);
+
     @Select({"<script> " +
             "select count(1) FROM fs_inquiry_order_report ior  " +
             " LEFT JOIN fs_user u ON u.user_id=ior.user_id " +

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

@@ -0,0 +1,75 @@
+package com.fs.his.mapper;
+
+import java.util.List;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.fs.his.domain.FsPhysicalReportTemplateField;
+import org.apache.ibatis.annotations.Param;
+
+/**
+ * 体检报告模板字段Mapper接口
+ *
+ * @author fs
+ * @date 2025-07-24
+ */
+public interface FsPhysicalReportTemplateFieldMapper extends BaseMapper<FsPhysicalReportTemplateField> {
+    /**
+     * 查询体检报告模板字段
+     *
+     * @param id 体检报告模板字段主键
+     * @return 体检报告模板字段
+     */
+    FsPhysicalReportTemplateField selectFsPhysicalReportTemplateFieldById(String id);
+
+    /**
+     * 查询体检报告模板字段列表
+     *
+     * @param fsPhysicalReportTemplateField 体检报告模板字段
+     * @return 体检报告模板字段集合
+     */
+    List<FsPhysicalReportTemplateField> selectFsPhysicalReportTemplateFieldList(FsPhysicalReportTemplateField fsPhysicalReportTemplateField);
+
+    /**
+     * 新增体检报告模板字段
+     *
+     * @param fsPhysicalReportTemplateField 体检报告模板字段
+     * @return 结果
+     */
+    int insertFsPhysicalReportTemplateField(FsPhysicalReportTemplateField fsPhysicalReportTemplateField);
+
+    /**
+     * 修改体检报告模板字段
+     *
+     * @param fsPhysicalReportTemplateField 体检报告模板字段
+     * @return 结果
+     */
+    int updateFsPhysicalReportTemplateField(FsPhysicalReportTemplateField fsPhysicalReportTemplateField);
+
+    /**
+     * 删除体检报告模板字段
+     *
+     * @param id 体检报告模板字段主键
+     * @return 结果
+     */
+    int deleteFsPhysicalReportTemplateFieldById(String id);
+
+    /**
+     * 批量删除体检报告模板字段
+     *
+     * @param ids 需要删除的数据主键集合
+     * @return 结果
+     */
+    int deleteFsPhysicalReportTemplateFieldByIds(String[] ids);
+
+    /**
+     * 批量插入模板自定义字段
+     *
+     * @param templateFieldList 插入数据
+     **/
+    void batchInsertFsPhysicalReportTemplateField(@Param("templateFieldList") List<FsPhysicalReportTemplateField> templateFieldList);
+
+    /**
+     * 删除自定也模板
+     * **/
+    void deleteTemplateFieldByTemplateId(@Param("templateId") Long templateId);
+}

+ 61 - 0
fs-service/src/main/java/com/fs/his/mapper/FsPhysicalReportTemplateMapper.java

@@ -0,0 +1,61 @@
+package com.fs.his.mapper;
+
+import java.util.List;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.fs.his.domain.FsPhysicalReportTemplate;
+
+/**
+ * 体检报告模板Mapper接口
+ * 
+ * @author fs
+ * @date 2025-07-23
+ */
+public interface FsPhysicalReportTemplateMapper extends BaseMapper<FsPhysicalReportTemplate>{
+    /**
+     * 查询体检报告模板
+     * 
+     * @param id 体检报告模板主键
+     * @return 体检报告模板
+     */
+    FsPhysicalReportTemplate selectFsPhysicalReportTemplateById(String id);
+
+    /**
+     * 查询体检报告模板列表
+     * 
+     * @param fsPhysicalReportTemplate 体检报告模板
+     * @return 体检报告模板集合
+     */
+    List<FsPhysicalReportTemplate> selectFsPhysicalReportTemplateList(FsPhysicalReportTemplate fsPhysicalReportTemplate);
+
+    /**
+     * 新增体检报告模板
+     * 
+     * @param fsPhysicalReportTemplate 体检报告模板
+     * @return 结果
+     */
+    int insertFsPhysicalReportTemplate(FsPhysicalReportTemplate fsPhysicalReportTemplate);
+
+    /**
+     * 修改体检报告模板
+     * 
+     * @param fsPhysicalReportTemplate 体检报告模板
+     * @return 结果
+     */
+    int updateFsPhysicalReportTemplate(FsPhysicalReportTemplate fsPhysicalReportTemplate);
+
+    /**
+     * 删除体检报告模板
+     * 
+     * @param id 体检报告模板主键
+     * @return 结果
+     */
+    int deleteFsPhysicalReportTemplateById(String id);
+
+    /**
+     * 批量删除体检报告模板
+     * 
+     * @param ids 需要删除的数据主键集合
+     * @return 结果
+     */
+    int deleteFsPhysicalReportTemplateByIds(String[] ids);
+}

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

@@ -1,7 +1,6 @@
 package com.fs.his.mapper;
 
 
-import com.fs.his.domain.FsStoreProductAttr;
 import com.fs.his.domain.FsStoreProductAttrValue;
 import com.fs.his.param.FsStoreProductAttrValueListDParam;
 import com.fs.his.vo.FsStoreProductAttrValueListDVO;
@@ -164,4 +163,11 @@ public interface FsStoreProductAttrValueMapper
 
     @Select("select * from fs_store_product_attr_value where product_id = #{productId}")
     List<FsStoreProductAttrValue> selectFsStoreProductAttrValueListByProductId(@Param("productId") Long productId);
+
+    /**
+     * 批量获取商品规格
+     * @param productIds
+     * @return productIds
+     * **/
+    List<FsStoreProductAttrValue> getFsStoreProductAttrValueListInProductId(@Param("productIds") List<Long> productIds);
 }

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

@@ -259,4 +259,10 @@ public interface FsStoreProductMapper {
     int updateStoreProductStock(@Param("productId") Long productId, @Param("stock") Integer stock);
 
 
+    /**
+     * 批量获取商品信息
+     * @param productIds
+     * @return List<FsStoreProduct>
+     * **/
+    List<FsStoreProduct> getStoreProductInProductIds(@Param("productIds") List<Long> productIds);
 }

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

@@ -18,6 +18,8 @@ public class FsInquiryOrderCreateParam implements Serializable {
 
     @NotEmpty(message = "病情描述不能为空")
     private String title;
+
+    private String companyUserRemark;
 //    @NotEmpty(message = "患病时长不能为空")
     private String duration;
 //    @NotEmpty(message = "是否就诊不能为空")
@@ -25,9 +27,12 @@ public class FsInquiryOrderCreateParam implements Serializable {
 
     @NotNull(message = "问诊类型不能为空")
     private Integer inquiryType;
+
     private Integer inquirySubType;
+
     @NotNull(message = "订单类型不能为空")
     private Integer orderType;
+
     private Long doctorId;
     private String reportImages;//检测报告
     private String tongueImages;//舌苔

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

@@ -156,6 +156,10 @@ public class FsStoreProductAddEditParam implements Serializable {
     @Excel(name = "运费模板")
     private Long tempId;
 
+    /** 品牌 */
+    @Excel(name = "品牌")
+    private String brand;
+
     //属性项目
     private List<ProductArrtDTO> items;
     //sku结果集

+ 80 - 0
fs-service/src/main/java/com/fs/his/service/IFsPhysicalReportTemplateFieldService.java

@@ -0,0 +1,80 @@
+package com.fs.his.service;
+
+import java.util.List;
+
+import com.baomidou.mybatisplus.extension.api.R;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.fs.his.domain.FsPhysicalReportTemplateField;
+import com.fs.his.dto.FsPhysicalReportTemplateFieldDTO;
+
+/**
+ * 体检报告模板字段Service接口
+ * 
+ * @author fs
+ * @date 2025-07-24
+ */
+public interface IFsPhysicalReportTemplateFieldService extends IService<FsPhysicalReportTemplateField>{
+    /**
+     * 查询体检报告模板字段
+     * 
+     * @param id 体检报告模板字段主键
+     * @return 体检报告模板字段
+     */
+    FsPhysicalReportTemplateField selectFsPhysicalReportTemplateFieldById(String id);
+
+    /**
+     * 查询体检报告模板字段列表
+     * 
+     * @param fsPhysicalReportTemplateField 体检报告模板字段
+     * @return 体检报告模板字段集合
+     */
+    List<FsPhysicalReportTemplateField> selectFsPhysicalReportTemplateFieldList(FsPhysicalReportTemplateField fsPhysicalReportTemplateField);
+
+    /**
+     * 新增体检报告模板字段
+     * 
+     * @param fsPhysicalReportTemplateField 体检报告模板字段
+     * @return 结果
+     */
+    int insertFsPhysicalReportTemplateField(FsPhysicalReportTemplateField fsPhysicalReportTemplateField);
+
+    /**
+     * 修改体检报告模板字段
+     * 
+     * @param fsPhysicalReportTemplateField 体检报告模板字段
+     * @return 结果
+     */
+    int updateFsPhysicalReportTemplateField(FsPhysicalReportTemplateField fsPhysicalReportTemplateField);
+
+    /**
+     * 批量删除体检报告模板字段
+     * 
+     * @param ids 需要删除的体检报告模板字段主键集合
+     * @return 结果
+     */
+    int deleteFsPhysicalReportTemplateFieldByIds(String[] ids);
+
+    /**
+     * 删除体检报告模板字段信息
+     * 
+     * @param id 体检报告模板字段主键
+     * @return 结果
+     */
+    int deleteFsPhysicalReportTemplateFieldById(String id);
+
+    /**
+     * 获取模板自定义字段
+     * @param templateId 模板ID
+     * @return R
+     * **/
+    R getTemplateField(String templateId);
+
+
+    /**
+     * 新增体检报告模板字段
+     *
+     * @param fieldDTO 体检报告模板字段
+     * @return 结果
+     */
+    int saveFsPhysicalReportTemplateField(FsPhysicalReportTemplateFieldDTO fieldDTO);
+}

+ 61 - 0
fs-service/src/main/java/com/fs/his/service/IFsPhysicalReportTemplateService.java

@@ -0,0 +1,61 @@
+package com.fs.his.service;
+
+import java.util.List;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.fs.his.domain.FsPhysicalReportTemplate;
+
+/**
+ * 体检报告模板Service接口
+ * 
+ * @author fs
+ * @date 2025-07-23
+ */
+public interface IFsPhysicalReportTemplateService extends IService<FsPhysicalReportTemplate>{
+    /**
+     * 查询体检报告模板
+     * 
+     * @param id 体检报告模板主键
+     * @return 体检报告模板
+     */
+    FsPhysicalReportTemplate selectFsPhysicalReportTemplateById(String id);
+
+    /**
+     * 查询体检报告模板列表
+     * 
+     * @param fsPhysicalReportTemplate 体检报告模板
+     * @return 体检报告模板集合
+     */
+    List<FsPhysicalReportTemplate> selectFsPhysicalReportTemplateList(FsPhysicalReportTemplate fsPhysicalReportTemplate);
+
+    /**
+     * 新增体检报告模板
+     * 
+     * @param fsPhysicalReportTemplate 体检报告模板
+     * @return 结果
+     */
+    int insertFsPhysicalReportTemplate(FsPhysicalReportTemplate fsPhysicalReportTemplate);
+
+    /**
+     * 修改体检报告模板
+     * 
+     * @param fsPhysicalReportTemplate 体检报告模板
+     * @return 结果
+     */
+    int updateFsPhysicalReportTemplate(FsPhysicalReportTemplate fsPhysicalReportTemplate);
+
+    /**
+     * 批量删除体检报告模板
+     * 
+     * @param ids 需要删除的体检报告模板主键集合
+     * @return 结果
+     */
+    int deleteFsPhysicalReportTemplateByIds(String[] ids);
+
+    /**
+     * 删除体检报告模板信息
+     * 
+     * @param id 体检报告模板主键
+     * @return 结果
+     */
+    int deleteFsPhysicalReportTemplateById(String id);
+}

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

@@ -68,4 +68,11 @@ public interface IFsStoreProductAttrValueService
     int updateStoreProductAttrValueStock(Long id , Integer stock);
 
     List<FsStoreProductAttrValue> selectFsStoreProductAttrValueListByProductId( Long productId);
+
+    /**
+     * 批量获取商品规格
+     * @param productIds
+     * @return productIds
+     * **/
+    List<FsStoreProductAttrValue> getFsStoreProductAttrValueListInProductId(List<Long> productIds);
 }

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

@@ -97,4 +97,11 @@ public interface IFsStoreProductService
     FsStoreProduct getStoreProductByProductIdAndStoreId(Long productId, Long storeId);
 
     int updateStoreProductStock(Long productId, Integer num);
+
+    /**
+     * 批量获取商品信息
+     * @param productIds
+     * @return List<FsStoreProduct>
+     * **/
+    List<FsStoreProduct> getStoreProductInProductIds(List<Long> productIds);
 }

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

@@ -536,7 +536,6 @@ public class FsInquiryOrderServiceImpl implements IFsInquiryOrderService
         fsInquiryOrderLogsService.insertFsInquiryOrderLogs(log);
         return R.ok("操作成功");
     }
-
     @Override
     @Transactional
     public R createOrder(FsInquiryOrderCreateParam param) {
@@ -597,6 +596,7 @@ public class FsInquiryOrderServiceImpl implements IFsInquiryOrderService
         order.setUserId(param.getUserId());
         order.setPatientId(patient.getPatientId());
         order.setInquirySubType(param.getInquirySubType());
+        order.setCompanyUserRemark(param.getCompanyUserRemark());
         if (param.getSource()!=null){
             order.setSource(param.getSource());
         }

+ 153 - 0
fs-service/src/main/java/com/fs/his/service/impl/FsPhysicalReportTemplateFieldServiceImpl.java

@@ -0,0 +1,153 @@
+package com.fs.his.service.impl;
+
+import java.util.Date;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.extension.api.R;
+import com.fs.common.exception.ServiceException;
+import com.fs.common.utils.DateUtils;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.fs.common.utils.StringUtils;
+import com.fs.his.domain.FsPhysicalReportTemplate;
+import com.fs.his.dto.FsPhysicalReportTemplateFieldDTO;
+import com.fs.his.mapper.FsPhysicalReportTemplateMapper;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.fs.his.mapper.FsPhysicalReportTemplateFieldMapper;
+import com.fs.his.domain.FsPhysicalReportTemplateField;
+import com.fs.his.service.IFsPhysicalReportTemplateFieldService;
+import org.springframework.transaction.annotation.Transactional;
+
+/**
+ * 体检报告模板字段Service业务层处理
+ *
+ * @author fs
+ * @date 2025-07-24
+ */
+@Service
+public class FsPhysicalReportTemplateFieldServiceImpl extends ServiceImpl<FsPhysicalReportTemplateFieldMapper, FsPhysicalReportTemplateField> implements IFsPhysicalReportTemplateFieldService {
+
+    @Autowired
+    private FsPhysicalReportTemplateMapper physicalReportTemplateMapper;
+
+
+    /**
+     * 查询体检报告模板字段
+     *
+     * @param id 体检报告模板字段主键
+     * @return 体检报告模板字段
+     */
+    @Override
+    public FsPhysicalReportTemplateField selectFsPhysicalReportTemplateFieldById(String id) {
+        return baseMapper.selectFsPhysicalReportTemplateFieldById(id);
+    }
+
+    /**
+     * 查询体检报告模板字段列表
+     *
+     * @param fsPhysicalReportTemplateField 体检报告模板字段
+     * @return 体检报告模板字段
+     */
+    @Override
+    public List<FsPhysicalReportTemplateField> selectFsPhysicalReportTemplateFieldList(FsPhysicalReportTemplateField fsPhysicalReportTemplateField) {
+        return baseMapper.selectFsPhysicalReportTemplateFieldList(fsPhysicalReportTemplateField);
+    }
+
+    /**
+     * 新增体检报告模板字段
+     *
+     * @param fsPhysicalReportTemplateField 体检报告模板字段
+     * @return 结果
+     */
+    @Override
+    public int insertFsPhysicalReportTemplateField(FsPhysicalReportTemplateField fsPhysicalReportTemplateField) {
+        fsPhysicalReportTemplateField.setCreateTime(DateUtils.getNowDate());
+        return baseMapper.insertFsPhysicalReportTemplateField(fsPhysicalReportTemplateField);
+    }
+
+    /**
+     * 修改体检报告模板字段
+     *
+     * @param fsPhysicalReportTemplateField 体检报告模板字段
+     * @return 结果
+     */
+    @Override
+    public int updateFsPhysicalReportTemplateField(FsPhysicalReportTemplateField fsPhysicalReportTemplateField) {
+        fsPhysicalReportTemplateField.setUpdateTime(DateUtils.getNowDate());
+        return baseMapper.updateFsPhysicalReportTemplateField(fsPhysicalReportTemplateField);
+    }
+
+    /**
+     * 批量删除体检报告模板字段
+     *
+     * @param ids 需要删除的体检报告模板字段主键
+     * @return 结果
+     */
+    @Override
+    public int deleteFsPhysicalReportTemplateFieldByIds(String[] ids) {
+        return baseMapper.deleteFsPhysicalReportTemplateFieldByIds(ids);
+    }
+
+    /**
+     * 删除体检报告模板字段信息
+     *
+     * @param id 体检报告模板字段主键
+     * @return 结果
+     */
+    @Override
+    public int deleteFsPhysicalReportTemplateFieldById(String id) {
+        return baseMapper.deleteFsPhysicalReportTemplateFieldById(id);
+    }
+
+    @Override
+    public R getTemplateField(String templateId) {
+        //查询模板信息是否存在
+        FsPhysicalReportTemplate reportTemplate = physicalReportTemplateMapper.selectById(templateId);
+        if (StringUtils.isNull(reportTemplate)) {
+            return R.failed("操作失败,模板信息不存在!");
+        } else if (!reportTemplate.getStatus().equals("1")) {
+            return R.failed("操作失败,当前模板已禁用!");
+        }
+
+        //查询模板下自定义数据信息
+        return R.ok(baseMapper.selectList(new LambdaQueryWrapper<FsPhysicalReportTemplateField>().eq(FsPhysicalReportTemplateField::getTemplateId, templateId).orderByAsc(FsPhysicalReportTemplateField::getSort)));
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public int saveFsPhysicalReportTemplateField(FsPhysicalReportTemplateFieldDTO fieldDTO) {
+        //查询模板信息是否存在
+        FsPhysicalReportTemplate reportTemplate = physicalReportTemplateMapper.selectById(fieldDTO.getTemplateId());
+        if (StringUtils.isNull(reportTemplate)) {
+            throw new ServiceException("操作失败,模板信息不存在!");
+        } else if (!reportTemplate.getStatus().equals("1")) {
+            throw new ServiceException("操作失败,当前模板已禁用!");
+        }
+
+        //验证数据主要数据是否存在
+        AtomicInteger num = new AtomicInteger();
+        Date date=new Date();
+        fieldDTO.getTemplateFieldList().forEach(t -> {
+            num.getAndIncrement();
+            if (StringUtils.isNull(t.getComponentId())) {
+                throw new ServiceException("操作失败,模板ID不能为空!");
+            } else if (StringUtils.isNull(t.getLabel())) {
+                throw new ServiceException("操作失败,组件名称不能为空!");
+            } else if (StringUtils.isNull(t.getType())) {
+                throw new ServiceException("操作失败,字段类型不能为空!");
+            }
+            t.setCreateBy(fieldDTO.getCreateBy());
+            t.setTemplateId(reportTemplate.getId());
+            t.setCreateTime(date);
+            t.setSort(num.get());
+        });
+
+        //删除相关数据
+        baseMapper.deleteTemplateFieldByTemplateId(reportTemplate.getId());
+        //批量插入
+        baseMapper.batchInsertFsPhysicalReportTemplateField(fieldDTO.getTemplateFieldList());
+        return 1;
+    }
+}

+ 125 - 0
fs-service/src/main/java/com/fs/his/service/impl/FsPhysicalReportTemplateServiceImpl.java

@@ -0,0 +1,125 @@
+package com.fs.his.service.impl;
+
+import java.util.List;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.extension.service.additional.query.impl.LambdaQueryChainWrapper;
+import com.fs.common.exception.ServiceException;
+import com.fs.common.utils.DateUtils;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.fs.common.utils.StringUtils;
+import com.fs.huifuPay.sdk.opps.core.utils.ObjectUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.fs.his.mapper.FsPhysicalReportTemplateMapper;
+import com.fs.his.domain.FsPhysicalReportTemplate;
+import com.fs.his.service.IFsPhysicalReportTemplateService;
+import org.springframework.transaction.annotation.Transactional;
+
+/**
+ * 体检报告模板Service业务层处理
+ *
+ * @author fs
+ * @date 2025-07-23
+ */
+@Service
+public class FsPhysicalReportTemplateServiceImpl extends ServiceImpl<FsPhysicalReportTemplateMapper, FsPhysicalReportTemplate> implements IFsPhysicalReportTemplateService {
+
+    /**
+     * 查询体检报告模板
+     *
+     * @param id 体检报告模板主键
+     * @return 体检报告模板
+     */
+    @Override
+    public FsPhysicalReportTemplate selectFsPhysicalReportTemplateById(String id) {
+        return baseMapper.selectFsPhysicalReportTemplateById(id);
+    }
+
+    /**
+     * 查询体检报告模板列表
+     *
+     * @param fsPhysicalReportTemplate 体检报告模板
+     * @return 体检报告模板
+     */
+    @Override
+    public List<FsPhysicalReportTemplate> selectFsPhysicalReportTemplateList(FsPhysicalReportTemplate fsPhysicalReportTemplate) {
+        return baseMapper.selectFsPhysicalReportTemplateList(fsPhysicalReportTemplate);
+    }
+
+    /**
+     * 新增体检报告模板
+     *
+     * @param fsPhysicalReportTemplate 体检报告模板
+     * @return 结果
+     */
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public int insertFsPhysicalReportTemplate(FsPhysicalReportTemplate fsPhysicalReportTemplate) {
+        //验证模板是否存在
+        if (baseMapper.selectCount(new LambdaQueryWrapper<FsPhysicalReportTemplate>().eq(FsPhysicalReportTemplate::getTemplateName, fsPhysicalReportTemplate.getTemplateName()).eq(FsPhysicalReportTemplate::getStatus, "1")) > 0) {
+            throw new ServiceException("操作失败,当前模板:" + fsPhysicalReportTemplate.getTemplateName() + "名称已存在!");
+        }
+
+        fsPhysicalReportTemplate.setCreateTime(DateUtils.getNowDate());
+        return baseMapper.insertFsPhysicalReportTemplate(fsPhysicalReportTemplate);
+    }
+
+    /**
+     * 修改体检报告模板
+     *
+     * @param fsPhysicalReportTemplate 体检报告模板
+     * @return 结果
+     */
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public int updateFsPhysicalReportTemplate(FsPhysicalReportTemplate fsPhysicalReportTemplate) {
+        //验证修改数据是否存在
+        FsPhysicalReportTemplate reportTemplate = baseMapper.selectById(fsPhysicalReportTemplate.getId());
+        if (StringUtils.isNull(reportTemplate)) {
+            throw new ServiceException("操作失败,修改数据不存在!");
+        }
+
+        //验证模板是否存在
+        if (baseMapper.selectCount(new LambdaQueryWrapper<FsPhysicalReportTemplate>().eq(FsPhysicalReportTemplate::getTemplateName, fsPhysicalReportTemplate.getTemplateName()).eq(FsPhysicalReportTemplate::getStatus, "1").ne(FsPhysicalReportTemplate::getId, fsPhysicalReportTemplate.getId())) > 0) {
+            throw new ServiceException("操作失败,当前模板:" + fsPhysicalReportTemplate.getTemplateName() + "名称已存在!");
+        }
+
+        fsPhysicalReportTemplate.setUpdateTime(DateUtils.getNowDate());
+        return baseMapper.updateFsPhysicalReportTemplate(fsPhysicalReportTemplate);
+    }
+
+    /**
+     * 批量删除体检报告模板
+     *
+     * @param ids 需要删除的体检报告模板主键
+     * @return 结果
+     */
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public int deleteFsPhysicalReportTemplateByIds(String[] ids) {
+        //验证删除数据是否存在启用数据
+        List<FsPhysicalReportTemplate> reportTemplateList = baseMapper.selectList(new LambdaQueryWrapper<FsPhysicalReportTemplate>().in(FsPhysicalReportTemplate::getId, ids));
+        if (reportTemplateList.isEmpty() || reportTemplateList.size() != ids.length) {
+            throw new ServiceException("操作失败,删除数据不匹配!");
+        }
+        //校验数据数据状态是否
+        String templateName = reportTemplateList.stream().filter(r -> r.getStatus().equals("1")).findFirst().map(FsPhysicalReportTemplate::getTemplateName).orElse(null);
+        if (StringUtils.isNotEmpty(templateName)) {
+            throw new ServiceException("操作失败,当前模板:" + templateName + "正在启用中,无法删除!");
+        }
+
+        return baseMapper.deleteFsPhysicalReportTemplateByIds(ids);
+    }
+
+    /**
+     * 删除体检报告模板信息
+     *
+     * @param id 体检报告模板主键
+     * @return 结果
+     */
+    @Override
+    public int deleteFsPhysicalReportTemplateById(String id) {
+        return baseMapper.deleteFsPhysicalReportTemplateById(id);
+    }
+}

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

@@ -1596,6 +1596,8 @@ public class FsStoreOrderServiceImpl implements IFsStoreOrderService
             return;
         }
         IErpOrderService erpOrderService = null;
+        ErpOrder erpOrder = new ErpOrder();
+        erpOrder.setShop_code(sysConfig.getErpShopCode());
         if (erpType == 1) {
             //管易
             erpOrderService = gyOrderService;
@@ -1611,6 +1613,7 @@ public class FsStoreOrderServiceImpl implements IFsStoreOrderService
         } else if (erpType == 5){
             //聚水潭
             erpOrderService =  jSTOrderService;
+            erpOrder.setShop_code(sysConfig.getErpJstShopCode());
         }else {
             return;
         }
@@ -1621,7 +1624,7 @@ public class FsStoreOrderServiceImpl implements IFsStoreOrderService
         if (order == null) {
             return;
         }
-        ErpOrder erpOrder = new ErpOrder();
+
         if (order.getCompanyId() != null) {
             erpOrder.setVip_code(order.getUserId().toString() + order.getCompanyId().toString());
         } else {
@@ -1629,7 +1632,7 @@ public class FsStoreOrderServiceImpl implements IFsStoreOrderService
         }
         erpOrder.setPlatform_code(order.getOrderCode());
 
-        erpOrder.setShop_code(sysConfig.getErpShopCode());
+        erpOrder.setBuyer_account(order.getUserName());
         erpOrder.setSeller_memo(order.getRemark());
         List<ErpOrderPayment> payments = new ArrayList<>();
         ErpOrderPayment payment = new ErpOrderPayment();

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

@@ -113,4 +113,9 @@ public class FsStoreProductAttrValueServiceImpl implements IFsStoreProductAttrVa
     public List<FsStoreProductAttrValue> selectFsStoreProductAttrValueListByProductId( Long productId){
         return fsStoreProductAttrValueMapper.selectFsStoreProductAttrValueListByProductId(productId);
     }
+
+    @Override
+    public List<FsStoreProductAttrValue> getFsStoreProductAttrValueListInProductId(List<Long> productIds) {
+        return fsStoreProductAttrValueMapper.getFsStoreProductAttrValueListInProductId(productIds);
+    }
 }

+ 50 - 6
fs-service/src/main/java/com/fs/his/service/impl/FsStoreProductServiceImpl.java

@@ -19,6 +19,7 @@ import com.fs.common.exception.ServiceException;
 import com.fs.common.utils.DateUtils;
 import com.fs.erp.domain.ErpGoods;
 import com.fs.erp.service.IErpGoodsService;
+import com.fs.erp.service.IErpOrderService;
 import com.fs.his.config.FsSysConfig;
 import com.fs.his.domain.*;
 import com.fs.his.dto.FsPackagePruductDTO;
@@ -71,6 +72,12 @@ public class FsStoreProductServiceImpl implements IFsStoreProductService {
     @Qualifier("hzOMSErpGoodsServiceImpl")
     private IErpGoodsService hzOMSErpGoodsService;
 
+    @Autowired
+    @Qualifier("JSTErpGoodsServiceImpl")
+    private IErpGoodsService jSTErpGoodsService;
+
+
+
     /**
      * 查询商品
      *
@@ -451,7 +458,9 @@ public class FsStoreProductServiceImpl implements IFsStoreProductService {
     @Transactional
     public R addOrEdit(FsStoreProductAddEditParam param) {
         ProductAttrCountDTO countDto = computedProductCount(param.getValues());
-
+        FsSysConfig sysConfig = configUtil.getSysConfig();
+        Integer erpOpen = sysConfig.getErpOpen();
+        ErpGoods params = new ErpGoods();
         if (param.getProductId() != null) {
             FsStoreProduct product = new FsStoreProduct();
             BeanUtils.copyProperties(param, product);
@@ -504,7 +513,22 @@ public class FsStoreProductServiceImpl implements IFsStoreProductService {
                     pack.setProductJson(JSON.toJSONString(products));
                     fsPackageService.updateFsPackage(pack);
                 }
+            }
 
+            //todo 添加商品HzOMSerp调用
+            //判断是否开启erp
+            if (erpOpen == null || erpOpen == 0) {
+                //不作操作
+            } else {
+                //判断erp类型
+                Integer erpType = sysConfig.getErpType();
+                if (erpType == null) {
+                    //不作操作
+                } else if (erpType == 5){
+                    //聚水潭商品同步
+                    params.setProductIdList(Arrays.asList(product.getProductId()));
+                    jSTErpGoodsService.addGoods(params);
+                }
             }
         } else {
             FsStoreProduct product = new FsStoreProduct();
@@ -512,6 +536,7 @@ public class FsStoreProductServiceImpl implements IFsStoreProductService {
             product.setPrice(countDto.getMinPrice());
             product.setOtPrice(countDto.getMinOtPrice());
             product.setCostPrice(countDto.getMinCost());
+            product.setBarCode(param.getValues().get(0).getBarCode());
             product.setGiveIntegral(new BigDecimal(countDto.getMinIntegral()));
             product.setStock(countDto.getStock());
             fsStoreProductMapper.insertFsStoreProduct(product);
@@ -527,10 +552,9 @@ public class FsStoreProductServiceImpl implements IFsStoreProductService {
             } else {
                 addProductAttr(product.getProductId(), param.getItems(), param.getValues());
             }
+
             //todo 添加商品HzOMSerp调用
             //判断是否开启erp
-            FsSysConfig sysConfig = configUtil.getSysConfig();
-            Integer erpOpen = sysConfig.getErpOpen();
             if (erpOpen == null || erpOpen == 0) {
                 //不作操作
             } else {
@@ -539,14 +563,15 @@ public class FsStoreProductServiceImpl implements IFsStoreProductService {
                 if (erpType == null) {
                     //不作操作
                 } else if (erpType == 3) {
-                    ErpGoods params = new ErpGoods();
                     params.setStoreProductId(product.getProductId());
                     //瀚智OMS 维护添加商品
                     hzOMSErpGoodsService.addGoods(params);
+                }else if (erpType == 5){
+                    //聚水潭商品同步
+                    params.setProductIdList(Arrays.asList(product.getProductId()));
+                    jSTErpGoodsService.addGoods(params);
                 }
             }
-
-
         }
         return R.ok();
     }
@@ -652,6 +677,8 @@ public class FsStoreProductServiceImpl implements IFsStoreProductService {
         StringBuilder successMsg = new StringBuilder();
         StringBuilder failureMsg = new StringBuilder();
 
+        //存储商品Id
+        List<Long> jstProductIds=new LinkedList<>();
         for (FsStoreProductExcelVO productVO : productList) {
             try {
 
@@ -738,6 +765,7 @@ public class FsStoreProductServiceImpl implements IFsStoreProductService {
                 fsStoreProductAttrMapper.insertFsStoreProductAttr(attr);
                 successNum++;
                 successMsg.append("<br/>" + successNum + "、商品 " + product.getProductName() + " 导入成功");
+
                 //todo 添加商品HzOMSerp调用
                 //判断是否开启erp
                 FsSysConfig sysConfig = configUtil.getSysConfig();
@@ -754,6 +782,8 @@ public class FsStoreProductServiceImpl implements IFsStoreProductService {
                         params.setStoreProductId(product.getProductId());
                         //瀚智OMS 维护添加商品
                         hzOMSErpGoodsService.addGoods(params);
+                    }else if(erpType == 5){
+                        jstProductIds.add(product.getProductId());
                     }
                 }
             } catch (Exception e) {
@@ -763,6 +793,16 @@ public class FsStoreProductServiceImpl implements IFsStoreProductService {
                 failureMsg.append(msg + e.getMessage());
             }
         }
+
+        //验证聚水潭商品Id
+        if(!jstProductIds.isEmpty()){
+            //同步聚水潭商品
+            ErpGoods params = new ErpGoods();
+            params.setProductIdList(jstProductIds);
+            jSTErpGoodsService.addGoods(params);
+        }
+
+
         if (failureNum > 0) {
             failureMsg.insert(0, "很抱歉,导入失败!共 " + failureNum + " 条数据格式不正确,错误如下:");
             throw new ServiceException(failureMsg.toString());
@@ -826,4 +866,8 @@ public class FsStoreProductServiceImpl implements IFsStoreProductService {
         return fsStoreProductMapper.updateStoreProductStock(productId, num);
     }
 
+    @Override
+    public List<FsStoreProduct> getStoreProductInProductIds(List<Long> productIds) {
+        return fsStoreProductMapper.getStoreProductInProductIds(productIds);
+    }
 }

+ 11 - 2
fs-service/src/main/java/com/fs/qw/domain/QwMaterial.java

@@ -1,5 +1,7 @@
 package com.fs.qw.domain;
 
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
 import com.fasterxml.jackson.annotation.JsonFormat;
 import com.fs.common.annotation.Excel;
 import com.fs.common.core.domain.BaseEntity;
@@ -14,11 +16,12 @@ import java.util.Date;
  * @date 2024-06-20
  */
 @Data
-public class QwMaterial extends BaseEntity
+public class QwMaterial
 {
     private static final long serialVersionUID = 1L;
 
     /** 素材库id */
+    @TableId(type = IdType.AUTO)
     private Long materialId;
 
     /** 媒体文件类型,分别有图片(image),语音(voice),视频(video),普通文件(file) */
@@ -31,7 +34,7 @@ public class QwMaterial extends BaseEntity
 
     /** 媒体文件上传时间戳 */
     @Excel(name = "媒体文件上传时间戳")
-    private String createdAt;
+    private Long createdAt;
 
     /** 文件地址,图片可以上传永久的,其他类型的3天有效 */
     @Excel(name = "文件地址,图片可以上传永久的,其他类型的3天有效")
@@ -74,6 +77,12 @@ public class QwMaterial extends BaseEntity
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     private Date createTime;
 
+    /**
+     *  更新时间
+     */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date updateTime;
+
 
     /**
      *  素材分类 1 普通素材组 2 朋友圈素材组

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

@@ -1,6 +1,7 @@
 package com.fs.qw.mapper;
 
 
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.fs.qw.domain.QwMaterial;
 import com.fs.qw.param.QwMaterialParam;
 import com.fs.qw.vo.QwMaterialVO;
@@ -15,7 +16,7 @@ import java.util.List;
  * @author fs
  * @date 2024-06-20
  */
-public interface QwMaterialMapper
+public interface QwMaterialMapper extends BaseMapper<QwMaterial>
 {
     /**
      * 查询素材库
@@ -107,4 +108,7 @@ public interface QwMaterialMapper
      * @return 结果
      */
     public int deleteQwMaterialByMaterialIds(Long[] materialIds);
+    public List<QwMaterial> selectQwMaterialListByMediaIdList();
+
+
 }

+ 6 - 1
fs-service/src/main/java/com/fs/qw/param/QwMaterialParam.java

@@ -1,10 +1,12 @@
 package com.fs.qw.param;
 
+import com.baomidou.mybatisplus.annotation.TableField;
 import com.fasterxml.jackson.annotation.JsonFormat;
 import com.fs.common.annotation.Excel;
 import com.fs.common.core.domain.BaseEntity;
 import lombok.Data;
 
+import java.io.Serializable;
 import java.util.Date;
 
 /**
@@ -14,7 +16,7 @@ import java.util.Date;
  * @date 2024-06-20
  */
 @Data
-public class QwMaterialParam extends BaseEntity
+public class QwMaterialParam extends BaseEntity implements Serializable
 {
     private static final long serialVersionUID = 1L;
 
@@ -79,4 +81,7 @@ public class QwMaterialParam extends BaseEntity
      *  素材分类 1 普通素材组 2 朋友圈素材组
      */
     private Integer groupType;
+
+    @TableField(exist = false)
+    private String QwUserId;
 }

+ 28 - 0
fs-service/src/main/java/com/fs/qw/param/QwMaterialParamBySidebar.java

@@ -0,0 +1,28 @@
+package com.fs.qw.param;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+
+@Data
+public class QwMaterialParamBySidebar  implements Serializable  {
+
+
+    @ApiModelProperty(value = "页码,默认为1", required = true)
+    private Integer pageNum = 1;
+
+    @ApiModelProperty(value = "页大小,默认为10", required = true)
+    private Integer pageSize = 10;
+
+    @ApiModelProperty(value = "模糊搜索,通过视频名称来匹配")
+    private String keyword;
+
+    @ApiModelProperty(value = "公司id")
+    private Long companyId;
+
+    private String corpId;
+
+    private String qwUserId;
+
+}

+ 8 - 0
fs-service/src/main/java/com/fs/qw/service/IQwMaterialService.java

@@ -63,4 +63,12 @@ public interface IQwMaterialService
      * @return 结果
      */
     public int deleteQwMaterialByMaterialId(Long materialId);
+
+    /**
+    * 定时更新 上传的企业微信素材库
+    */
+    public void updateQwMaterialByQw();
+
+    public QwMaterial selectQwMaterialByMaterialIdByTime(Long materialId) throws Exception;
+    public QwMaterial selectQwMaterialByMaterialIdByTimeTwo(Long materialId) throws Exception;
 }

+ 147 - 7
fs-service/src/main/java/com/fs/qw/service/impl/QwMaterialServiceImpl.java

@@ -1,6 +1,7 @@
 package com.fs.qw.service.impl;
 
 
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.fs.common.core.domain.R;
 import com.fs.common.utils.DateUtils;
 import com.fs.qw.domain.QwMaterial;
@@ -11,6 +12,7 @@ import com.fs.qw.vo.QwMaterialVO;
 import com.fs.qwApi.Result.QwUploadResult;
 import com.fs.qwApi.service.QwApiService;
 import com.fs.voice.utils.StringUtil;
+import lombok.extern.log4j.Log4j2;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
@@ -19,8 +21,14 @@ import java.io.File;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.net.URL;
+import java.util.ArrayList;
 import java.util.Date;
 import java.util.List;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.stream.Collectors;
 
 /**
  * 素材库Service业务层处理
@@ -28,8 +36,9 @@ import java.util.List;
  * @author fs
  * @date 2024-06-20
  */
+@Log4j2
 @Service
-public class QwMaterialServiceImpl implements IQwMaterialService
+public class QwMaterialServiceImpl extends ServiceImpl<QwMaterialMapper, QwMaterial> implements IQwMaterialService
 {
     @Autowired
     private QwMaterialMapper qwMaterialMapper;
@@ -73,14 +82,62 @@ public class QwMaterialServiceImpl implements IQwMaterialService
 
         //调用企业微信接口 上次临时图片
 
-        File fileImage = urlToFile(qwMaterial.getMaterialUrl());
-        QwUploadResult imageResult = qwApiService.upload(fileImage, "image", qwMaterial.getCorpId());
-        if (imageResult.getErrCode()==0){
-            qwMaterial.setMaterialMediaId(imageResult.getMediaId());
+        if ("text".equals(qwMaterial.getMaterialType())){
             qwMaterialMapper.insertQwMaterial(qwMaterial);
             return R.ok();
-        }else {
-            return R.error("上传图片失败:"+imageResult.getErrMsg());
+        }else if ("image".equals(qwMaterial.getMaterialType())
+                ||"video".equals(qwMaterial.getMaterialType())
+                ||"file".equals(qwMaterial.getMaterialType())){
+            return uploadAndSaveQwMaterial(qwMaterial);
+        }
+
+        return R.ok();
+
+    }
+
+    public R uploadAndSaveQwMaterial(QwMaterial qwMaterial){
+        try {
+            // 将URL转换为文件
+            File materialFile = urlToFile(qwMaterial.getMaterialUrl());
+
+            // 上传素材到企业微信
+            QwUploadResult uploadResult = qwApiService.upload(materialFile, qwMaterial.getMaterialType(), qwMaterial.getCorpId());
+
+            if (uploadResult.getErrCode() == 0) {
+                // 设置素材信息并保存到数据库
+                qwMaterial.setMaterialMediaId(uploadResult.getMediaId());
+                qwMaterial.setCreatedAt(Long.valueOf(uploadResult.getCreatedAt()));
+                qwMaterialMapper.insertQwMaterial(qwMaterial);
+                return R.ok();
+            } else {
+                return R.error("上传"+qwMaterial.getMaterialType()+"失败:" + uploadResult.getErrMsg());
+            }
+        } catch (Exception e) {
+            return R.error("处理"+qwMaterial.getMaterialType()+"时发生异常:" + e.getMessage());
+        }
+    }
+
+    public QwMaterial uploadAndSaveQwMaterialByDTO(QwMaterial qwMaterial){
+        try {
+            // 将URL转换为文件
+            File materialFile = urlToFile(qwMaterial.getMaterialUrl());
+
+            // 上传素材到企业微信
+            QwUploadResult uploadResult = qwApiService.upload(materialFile, qwMaterial.getMaterialType(), qwMaterial.getCorpId());
+
+            if (uploadResult.getErrCode() == 0) {
+                // 设置素材信息并保存到数据库
+                qwMaterial.setMaterialMediaId(uploadResult.getMediaId());
+                qwMaterial.setCreatedAt(Long.valueOf(uploadResult.getCreatedAt()));
+                qwMaterialMapper.insertQwMaterial(qwMaterial);
+                return qwMaterial;
+            } else {
+                log.error("上传DTO"+qwMaterial.getMaterialType()+"失败:" + uploadResult.getErrMsg());
+                return null;
+            }
+        } catch (Exception e) {
+            log.error("处理DTO"+qwMaterial.getMaterialType()+"时发生异常:" + e.getMessage());
+            return null;
         }
     }
 
@@ -188,6 +245,89 @@ public class QwMaterialServiceImpl implements IQwMaterialService
     @Override
     public int deleteQwMaterialByMaterialId(Long materialId)
     {
+        log.info("删除素材库中信息:{}",qwMaterialMapper.selectQwMaterialByMaterialId(materialId));
         return qwMaterialMapper.deleteQwMaterialByMaterialId(materialId);
     }
+
+    @Override
+    public void updateQwMaterialByQw() {
+
+        List<QwMaterial> qwMaterials = qwMaterialMapper.selectQwMaterialListByMediaIdList();
+
+
+        // 创建线程安全的集合用于存储处理结果
+        ConcurrentLinkedQueue<QwMaterial> successQueue = new ConcurrentLinkedQueue<>();
+
+        // 创建线程池
+        int threadPoolSize = Math.min(8, Runtime.getRuntime().availableProcessors() * 2);
+        ExecutorService executor = Executors.newFixedThreadPool(threadPoolSize);
+
+        try {
+            // 创建并执行所有异步任务
+            List<CompletableFuture<Void>> futures = qwMaterials.stream()
+                    .filter(item -> "image".equals(item.getMaterialType())
+                            || "video".equals(item.getMaterialType())
+                            || "file".equals(item.getMaterialType()))
+                    .map(item -> CompletableFuture.runAsync(() -> {
+                        try {
+                            // 将URL转换为文件
+                            File materialFile = urlToFile(item.getMaterialUrl());
+
+                            // 上传素材到企业微信
+                            QwUploadResult uploadResult = qwApiService.upload(
+                                    materialFile,
+                                    item.getMaterialType(),
+                                    item.getCorpId()
+                            );
+
+                            if (uploadResult.getErrCode() == 0) {
+                                // 设置素材信息
+                                item.setMaterialMediaId(uploadResult.getMediaId());
+                                item.setCreatedAt(Long.valueOf(uploadResult.getCreatedAt()));
+                                successQueue.add(item);
+                            } else {
+                                log.error("上传失败:{},{}", uploadResult.getErrMsg(), item);
+                            }
+                        } catch (Exception e) {
+                            log.error("上传失败异常:{},{}", e.getMessage(), item);
+                        }
+                    }, executor))
+                    .collect(Collectors.toList());
+
+            // 等待所有任务完成
+            CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();
+
+            // 批量更新成功的记录
+            if (!successQueue.isEmpty()) {
+                super.saveOrUpdateBatch(new ArrayList<>(successQueue),300);
+            }
+
+
+        } finally {
+            // 关闭线程池
+            executor.shutdown();
+        }
+    }
+
+    @Override
+    public QwMaterial selectQwMaterialByMaterialIdByTime(Long materialId) throws Exception {
+
+        return uploadAndSaveQwMaterialByDTO(qwMaterialMapper.selectQwMaterialByMaterialId(materialId));
+    }
+
+    @Override
+    public QwMaterial selectQwMaterialByMaterialIdByTimeTwo(Long materialId) throws Exception {
+
+        QwMaterial qwMaterial = qwMaterialMapper.selectQwMaterialByMaterialId(materialId);
+
+        Long createdAt = qwMaterial.getCreatedAt();
+        boolean isOver48h = createdAt != null
+                && (System.currentTimeMillis() / 1000 - createdAt) > 172800;
+
+        if (qwMaterial.getMaterialType() != null && isOver48h) {
+            return uploadAndSaveQwMaterialByDTO(qwMaterial);
+        }
+
+        return qwMaterial;
+    }
 }

+ 8 - 0
fs-service/src/main/java/com/fs/sop/domain/SopUserLogsInfo.java

@@ -73,6 +73,14 @@ public class SopUserLogsInfo implements Serializable {
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     private String inComingETime;
 
+    /**
+     * 营期时间
+     */
+    @TableField(exist = false)
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    private String startTime;
+
+
     @TableField(exist = false)
     private Integer level;
 

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

@@ -109,7 +109,7 @@ public interface SopUserLogsMapper {
 
     @DataSource(DataSourceType.SOP)
     @Select("<script>" +
-            "select li.sop_id,li.external_contact_id,li.qw_user_id,li.corp_id,li.external_id,li.external_user_name " +
+            "select li.sop_id,li.external_contact_id,li.qw_user_id,li.corp_id,li.external_id,li.external_user_name,li.fs_user_id,ul.start_time,li.is_days_not_study " +
             "from sop_user_logs ul  " +
             "left join  sop_user_logs_info li on ul.id=li.user_logs_id " +
             "        WHERE ul.id IN\n" +

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

@@ -276,7 +276,9 @@ public class QwSopTempServiceImpl implements IQwSopTempService
             Map<Long, List<QwSopTempContent>> contentMap = PubFun.listToMapByGroupList(contentList, QwSopTempContent::getRulesId);
             rulesList.forEach(e -> {
                 List<QwSopTempContent> contents = contentMap.get(e.getId());
-                e.setSetting(contents.stream().map(c -> JSON.parseObject(c.getContent())).collect(Collectors.toList()));
+                if (CollectionUtils.isNotEmpty(contents)){
+                    e.setSetting(contents.stream().map(c -> JSON.parseObject(c.getContent())).collect(Collectors.toList()));
+                }
             });
         }
         day.setList(rulesList);

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

@@ -805,7 +805,7 @@ public class SopUserLogsInfoServiceImpl implements ISopUserLogsInfoService {
                             break;
                         //小程序单独
                         case "4":
-                            addWatchLogIfNeeded(param.getSopId(), param.getVideoId(), param.getCourseId(),item.getFsUserId(), qwUserId, companyUserId, companyId, item.getExternalId(),param.getStartTime(),createTime );
+                            addWatchLogIfNeeded(item.getSopId(), param.getVideoId(), param.getCourseId(),item.getFsUserId(), qwUserId, companyUserId, companyId, item.getExternalId(),item.getStartTime(),createTime );
 
                             String linkByMiniApp = createLinkByMiniApp(st, param.getCorpId(), createTime, param.getCourseId(), param.getVideoId(),
                                     qwUserId, companyUserId, companyId, item.getExternalId(), config);
@@ -821,7 +821,7 @@ public class SopUserLogsInfoServiceImpl implements ISopUserLogsInfoService {
                             break;
                         //app
                         case "9":
-                            addWatchLogIfNeeded(param.getSopId(), param.getVideoId(), param.getCourseId(),item.getFsUserId(), qwUserId, companyUserId, companyId, item.getExternalId(),param.getStartTime(),createTime );
+                            addWatchLogIfNeeded(item.getSopId(), param.getVideoId(), param.getCourseId(),item.getFsUserId(), qwUserId, companyUserId, companyId, item.getExternalId(),item.getStartTime(),createTime );
 
                             QwCreateLinkByAppVO linkByApp = createLinkByApp(st, param.getCorpId(), createTime, param.getCourseId(), param.getVideoId(),
                                     qwUserId, companyUserId, companyId, item.getExternalId(), config,qwUser.getQwUserName(),contact.getFsUserId());
@@ -1144,8 +1144,8 @@ public class SopUserLogsInfoServiceImpl implements ISopUserLogsInfoService {
                 //小程序单独
                 case "4":
 
-                    addWatchLogIfNeeded(param.getSopId(), param.getVideoId(), param.getCourseId(),item.getFsUserId(), String.valueOf(qwUser.getId()), companyUserId, companyId,
-                            item.getExternalId(),param.getStartTime(),dataTime );
+                    addWatchLogIfNeeded(item.getSopId(), param.getVideoId(), param.getCourseId(),item.getFsUserId(), String.valueOf(qwUser.getId()), companyUserId, companyId,
+                            item.getExternalId(),item.getStartTime(),dataTime );
 
                     String linkByMiniApp = createLinkByMiniApp(st, param.getCorpId(), dataTime, param.getCourseId(), param.getVideoId(),
                             String.valueOf(qwUser.getId()), companyUserId, companyId, item.getExternalId(), config);

+ 92 - 0
fs-service/src/main/resources/application-config-druid-bjczwh.yml

@@ -0,0 +1,92 @@
+baidu:
+  token: 12313231232
+  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: wx76cbxxdb092a41ae   #德瑞康
+        secret: c737a274159xxxe977d665d87643b3
+        token: Ncbnd7lJvkripxxna6NAWCxCrvC
+        aesKey: HlEiBB55eaWUaeBVAQO3cWKWPYv1vOVQSq7nFNICw4E
+        msgDataFormat: JSON
+  cp:
+    corpId: wwde3xxxxx4380
+    appConfigs:
+      - agentId: 112121206
+        secret: prclvyFLixxxxxFc_wgm3MTnfY6ZEk #德瑞康
+        token: PPKOdAlCoMO
+        aesKey: PKvaxtpSv8NGpfTDm7VUHIK8Wok2ESyYX24qpXJAdMP
+  pay:
+    appId:  #微信公众号或者小程序等的appid
+    mchId:  #微信支付商户号
+    mchKey:  #微信支付商户密钥
+    subAppId:  #服务商模式下的子商户公众账号ID
+    subMchId:  #服务商模式下的子商户号
+    keyPath: c:\\cert\\apiclient_cert.p12 # p12证书的位置,可以指定绝对路径,也可以指定类路径(以classpath:开头)
+    notifyUrl: https://userapp.his.runtzh.com/app/wxpay/wxPayNotify
+  mp:
+    useRedis: false
+    redisConfig:
+      host: 127.0.0.1
+      port: 6379
+      timeout: 2000
+    configs:
+      - appId: wx090xxxx5456e # 第一个公众号的appid  //公众号名称:德瑞康
+        secret: dc70e9xxxx0aea6b7c52b7 # 公众号的appsecret--德瑞康
+        token: PPKOdAlCoMO # 接口配置里的Token值
+        aesKey: Eswa6VjwtVMCcw03qZy6fWllgrv5aytIA1SZPEU0kU2 # 接口配置里的EncodingAESKey值
+aifabu:  #爱链接
+  appKey: 7b471be905ab17e00f3b858c6710dd117601d008
+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://127.0.0.1:7771
+  h5CommonApi: http://127.0.0.1:7771
+nuonuo:
+  key: 10924508
+  secret: A2EB20764D304D16
+
+# 存储捅配置
+tencent_cloud_config:
+  secret_id: AKIDiMq9lDf2EOM9lIfqqfKo7FNgM5meD0sT
+  secret_key: u5SuS80342xzx8FRBukza9lVNHKNMSaB
+  bucket: czwh-1323137866
+  app_id: 1323137866
+  region: ap-chongqing
+  proxy: czwh
+tmp_secret_config:
+  secret_id: AKIDCj7NSNAovtqeJpBau8GZ4CGB71thXIxX
+  secret_key: lTB5zwqqz7CNhzDOWivFWedgfTBgxgBT
+  bucket: fs-1319721001
+  app_id: 1319721001
+  region: ap-chongqing
+  proxy: fs
+cloud_host:
+  company_name: 北京存在文化
+headerImg:
+  imgUrl:
+
+ipad:
+  ipadUrl: http://ipad.cdwjyyh.com
+  aiApi: 1212121212
+
+wx_miniapp_temp:
+  pay_order_temp_id:
+  inquiry_temp_id:
+
+

+ 3 - 2
fs-service/src/main/resources/application-config-druid-bnkc.yml

@@ -10,8 +10,8 @@ logging:
 wx:
   miniapp:
     configs:
-      - appid: wx29d26f63f836be7f   #云联优选
-        secret: a85bfaf0d8e243817f265a321684f6ec
+      - appid: wx65e5d520e35bf3f5   #百年康城
+        secret: 0040365041935f62cbba64851ed374b3 #百年康城
         token: Ncbnd7lJvkripVOpyTFAna6NAWCxCrvC
         aesKey: HlEiBB55eaWUaeBVAQO3cWKWPYv1vOVQSq7nFNICw4E
         msgDataFormat: JSON
@@ -82,6 +82,7 @@ headerImg:
   imgUrl: https://bnkc-1363824368.cos.ap-chongqing.myqcloud.com/fs/logo/bnkc.png
 ipad:
   ipadUrl: http://ipad.cdwjyyh.com
+  aiApi: 1212121212
 wx_miniapp_temp:
   pay_order_temp_id:
   inquiry_temp_id:

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

@@ -82,6 +82,7 @@ headerImg:
   imgUrl: https://drk-1363981074.cos.ap-chongqing.myqcloud.com/fs/logo/30d7a0d1ec31e5ac16c6e96d5ca76ad.png
 ipad:
   ipadUrl: http://ipad.cdwjyyh.com
+  aiApi: 1212121212
 wx_miniapp_temp:
   pay_order_temp_id:
   inquiry_temp_id:

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

@@ -82,6 +82,7 @@ headerImg:
   imgUrl: https://whhm-1361716159.cos.ap-chongqing.myqcloud.com/fs/logo/8d71d552783718d726149312bfca24a.png
 ipad:
   ipadUrl: http://ipad.cdwjyyh.com
+  aiApi: 1212121212
 wx_miniapp_temp:
   pay_order_temp_id:
   inquiry_temp_id:

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

@@ -87,6 +87,7 @@ headerImg:
   imgUrl: https://xiaofangke-1360933944.cos.ap-nanjing.myqcloud.com/xiaofangke/20250610/9c3fb587d224492e8b61f5dece0b8b7b.png
 ipad:
   ipadUrl: http://ipad.cdwjyyh.com
+  aiApi:
 wx_miniapp_temp:
   pay_order_temp_id: VXEvKaGNPFuJmhWK9O_QPrTZxe9umDCukq-maI8Vdek
   inquiry_temp_id: 9POPYeqhI48LOPvq-Rfoklze7H-9SlunJKh10Qt4_2I

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

@@ -87,9 +87,9 @@ wx_miniapp_temp:
   inquiry_temp_id:
 # 聚水潭API配置
 jst:
-  app_key: bd7a7d06a6d54377842f883f9a4c502a
-  app_secret: 1d112cb9d21d41e187ff824b5852f4cf
-  authorization_code: zzzzzz
+  app_key: a4b1fab173c84f67b3873857eea11d90 #聚水潭2025-07-25
+  app_secret: dfce1f8dc8a64ddc91212fc3fcdd9349 #聚水潭2025-07-25
+  authorization_code: 666666
   shop_code: "18461733"
 
 

+ 149 - 0
fs-service/src/main/resources/application-druid-bjczwh.yml

@@ -0,0 +1,149 @@
+# 数据源配置
+spring:
+    profiles:
+        include: config-druid-bjczwh,common
+    # redis 配置
+    redis:
+        host: r-bp1ylqods7sqn8gs4b.redis.rds.aliyuncs.com
+        port: 6379
+        # 数据库索引
+        database: 0
+        # 密码
+        password: Ylrz_1q2w3e4r5t6y
+        # 连接超时时间
+        timeout: 10s
+        lettuce:
+            pool:
+                # 连接池中的最小空闲连接
+                min-idle: 0
+                # 连接池中的最大空闲连接
+                max-idle: 8
+                # 连接池的最大数据库连接数
+                max-active: 100
+                # #连接池最大阻塞等待时间(使用负值表示没有限制)
+                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://rm-bp10925iw97l3b2hb.mysql.rds.aliyuncs.com:3306/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://rm-bp10925iw97l3b2hb.mysql.rds.aliyuncs.com:3306/fs_his_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-16xj8o92zp.rocketmq.cd.qcloud.tencenttdmq.com:8080
+    producer:
+        group: my-producer-group
+        access-key: ak16xj8o92zp984557f83ba2 # 替换为实际的 accessKey
+        secret-key: sk2ff1c6b15b74b888 # 替换为实际的 secretKey
+    consumer:
+        group: common-group
+        access-key: ak16xj8o92zp984557f83ba2 # 替换为实际的 accessKey
+        secret-key: sk2ff1c6b15b74b888 # 替换为实际的 secretKey
+

+ 175 - 0
fs-service/src/main/resources/mapper/his/FsPhysicalReportTemplateFieldMapper.xml

@@ -0,0 +1,175 @@
+<?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.his.mapper.FsPhysicalReportTemplateFieldMapper">
+    
+    <resultMap type="FsPhysicalReportTemplateField" id="FsPhysicalReportTemplateFieldResult">
+        <result property="id"    column="id"    />
+        <result property="templateId"    column="template_id"    />
+        <result property="componentId"    column="component_id"    />
+        <result property="label"    column="label"    />
+        <result property="remark"    column="remark"    />
+        <result property="type"    column="type"    />
+        <result property="sort"    column="sort"    />
+        <result property="required"    column="required"    />
+        <result property="multiple"    column="multiple"    />
+        <result property="multiples"    column="multiples"    />
+        <result property="maxLength"    column="max_length"    />
+        <result property="minLength"    column="min_length"    />
+        <result property="createTime"    column="create_time"    />
+        <result property="updateTime"    column="update_time"    />
+        <result property="status"    column="status"    />
+        <result property="createBy"    column="create_by"    />
+        <result property="updateBy"    column="update_by"    />
+    </resultMap>
+
+    <sql id="selectFsPhysicalReportTemplateFieldVo">
+        select id, template_id, component_id, label, remark, type, sort, required, multiple, multiples, max_length, min_length, create_time, update_time, status, create_by, update_by from fs_physical_report_template_field
+    </sql>
+
+    <select id="selectFsPhysicalReportTemplateFieldList" parameterType="FsPhysicalReportTemplateField" resultMap="FsPhysicalReportTemplateFieldResult">
+        <include refid="selectFsPhysicalReportTemplateFieldVo"/>
+        <where>  
+            <if test="templateId != null "> and template_id = #{templateId}</if>
+            <if test="componentId != null "> and component_id = #{componentId}</if>
+            <if test="label != null  and label != ''"> and label = #{label}</if>
+            <if test="type != null  and type != ''"> and type = #{type}</if>
+            <if test="sort != null "> and sort = #{sort}</if>
+            <if test="required != null "> and required = #{required}</if>
+            <if test="multiple != null "> and multiple = #{multiple}</if>
+            <if test="multiples != null  and multiples != ''"> and multiples = #{multiples}</if>
+            <if test="maxLength != null "> and max_length = #{maxLength}</if>
+            <if test="minLength != null "> and min_length = #{minLength}</if>
+            <if test="status != null "> and status = #{status}</if>
+        </where>
+    </select>
+    
+    <select id="selectFsPhysicalReportTemplateFieldById" parameterType="String" resultMap="FsPhysicalReportTemplateFieldResult">
+        <include refid="selectFsPhysicalReportTemplateFieldVo"/>
+        where id = #{id}
+    </select>
+        
+    <insert id="insertFsPhysicalReportTemplateField" parameterType="FsPhysicalReportTemplateField" useGeneratedKeys="true" keyProperty="id">
+        insert into fs_physical_report_template_field
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="templateId != null">template_id,</if>
+            <if test="componentId != null">component_id,</if>
+            <if test="label != null and label != ''">label,</if>
+            <if test="remark != null">remark,</if>
+            <if test="type != null and type != ''">type,</if>
+            <if test="sort != null">sort,</if>
+            <if test="required != null">required,</if>
+            <if test="multiple != null">multiple,</if>
+            <if test="multiples != null">multiples,</if>
+            <if test="maxLength != null">max_length,</if>
+            <if test="minLength != null">min_length,</if>
+            <if test="createTime != null">create_time,</if>
+            <if test="updateTime != null">update_time,</if>
+            <if test="status != null">status,</if>
+            <if test="createBy != null">create_by,</if>
+            <if test="updateBy != null">update_by,</if>
+         </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="templateId != null">#{templateId},</if>
+            <if test="componentId != null">#{componentId},</if>
+            <if test="label != null and label != ''">#{label},</if>
+            <if test="remark != null">#{remark},</if>
+            <if test="type != null and type != ''">#{type},</if>
+            <if test="sort != null">#{sort},</if>
+            <if test="required != null">#{required},</if>
+            <if test="multiple != null">#{multiple},</if>
+            <if test="multiples != null">#{multiples},</if>
+            <if test="maxLength != null">#{maxLength},</if>
+            <if test="minLength != null">#{minLength},</if>
+            <if test="createTime != null">#{createTime},</if>
+            <if test="updateTime != null">#{updateTime},</if>
+            <if test="status != null">#{status},</if>
+            <if test="createBy != null">#{createBy},</if>
+            <if test="updateBy != null">#{updateBy},</if>
+         </trim>
+    </insert>
+
+    <update id="updateFsPhysicalReportTemplateField" parameterType="FsPhysicalReportTemplateField">
+        update fs_physical_report_template_field
+        <trim prefix="SET" suffixOverrides=",">
+            <if test="templateId != null">template_id = #{templateId},</if>
+            <if test="componentId != null">component_id = #{componentId},</if>
+            <if test="label != null and label != ''">label = #{label},</if>
+            <if test="remark != null">remark = #{remark},</if>
+            <if test="type != null and type != ''">type = #{type},</if>
+            <if test="sort != null">sort = #{sort},</if>
+            <if test="required != null">required = #{required},</if>
+            <if test="multiple != null">multiple = #{multiple},</if>
+            <if test="multiples != null">multiples = #{multiples},</if>
+            <if test="maxLength != null">max_length = #{maxLength},</if>
+            <if test="minLength != null">min_length = #{minLength},</if>
+            <if test="createTime != null">create_time = #{createTime},</if>
+            <if test="updateTime != null">update_time = #{updateTime},</if>
+            <if test="status != null">status = #{status},</if>
+            <if test="createBy != null">create_by = #{createBy},</if>
+            <if test="updateBy != null">update_by = #{updateBy},</if>
+        </trim>
+        where id = #{id}
+    </update>
+
+    <delete id="deleteFsPhysicalReportTemplateFieldById" parameterType="String">
+        delete from fs_physical_report_template_field where id = #{id}
+    </delete>
+
+    <delete id="deleteFsPhysicalReportTemplateFieldByIds" parameterType="String">
+        delete from fs_physical_report_template_field where id in 
+        <foreach item="id" collection="array" open="(" separator="," close=")">
+            #{id}
+        </foreach>
+    </delete>
+
+    <insert id="batchInsertFsPhysicalReportTemplateField" parameterType="java.util.List">
+        insert into fs_physical_report_template_field
+        (
+        template_id,
+        component_id,
+        label,
+        remark,
+        type,
+        sort,
+        required,
+        multiple,
+        multiples,
+        max_length,
+        min_length,
+        create_time,
+        update_time,
+        status,
+        create_by,
+        update_by,
+        options
+        )
+        values
+        <foreach collection="templateFieldList" index="index" item="item" separator=",">
+            (
+            #{item.templateId},
+            #{item.componentId},
+            #{item.label},
+            #{item.remark},
+            #{item.type},
+            #{item.sort},
+            #{item.required},
+            #{item.multiple},
+            #{item.multiples},
+            #{item.maxLength},
+            #{item.minLength},
+            #{item.createTime},
+            #{item.updateTime},
+            #{item.status},
+            #{item.createBy},
+            #{item.updateBy},
+            #{item.options}
+            )
+        </foreach>
+    </insert>
+
+    <delete id="deleteTemplateFieldByTemplateId">
+        delete from fs_physical_report_template_field where template_id = #{templateId}
+    </delete>
+</mapper>

+ 81 - 0
fs-service/src/main/resources/mapper/his/FsPhysicalReportTemplateMapper.xml

@@ -0,0 +1,81 @@
+<?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.his.mapper.FsPhysicalReportTemplateMapper">
+    
+    <resultMap type="FsPhysicalReportTemplate" id="FsPhysicalReportTemplateResult">
+        <result property="id"    column="id"    />
+        <result property="templateName"    column="template_name"    />
+        <result property="remark"    column="remark"    />
+        <result property="createTime"    column="create_time"    />
+        <result property="updateTime"    column="update_time"    />
+        <result property="status"    column="status"    />
+        <result property="createBy"    column="create_by"    />
+        <result property="updateBy"    column="update_by"    />
+    </resultMap>
+
+    <sql id="selectFsPhysicalReportTemplateVo">
+        select id, template_name, remark, create_time, update_time, status, create_by, update_by from fs_physical_report_template
+    </sql>
+
+    <select id="selectFsPhysicalReportTemplateList" parameterType="FsPhysicalReportTemplate" resultMap="FsPhysicalReportTemplateResult">
+        <include refid="selectFsPhysicalReportTemplateVo"/>
+        <where>  
+            <if test="templateName != null  and templateName != ''"> and template_name like concat('%', #{templateName}, '%')</if>
+            <if test="status != null "> and status = #{status}</if>
+        </where>
+    </select>
+    
+    <select id="selectFsPhysicalReportTemplateById" parameterType="String" resultMap="FsPhysicalReportTemplateResult">
+        <include refid="selectFsPhysicalReportTemplateVo"/>
+        where id = #{id}
+    </select>
+        
+    <insert id="insertFsPhysicalReportTemplate" parameterType="FsPhysicalReportTemplate" useGeneratedKeys="true" keyProperty="id">
+        insert into fs_physical_report_template
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="templateName != null and templateName != ''">template_name,</if>
+            <if test="remark != null">remark,</if>
+            <if test="createTime != null">create_time,</if>
+            <if test="updateTime != null">update_time,</if>
+            <if test="status != null">status,</if>
+            <if test="createBy != null">create_by,</if>
+            <if test="updateBy != null">update_by,</if>
+         </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="templateName != null and templateName != ''">#{templateName},</if>
+            <if test="remark != null">#{remark},</if>
+            <if test="createTime != null">#{createTime},</if>
+            <if test="updateTime != null">#{updateTime},</if>
+            <if test="status != null">#{status},</if>
+            <if test="createBy != null">#{createBy},</if>
+            <if test="updateBy != null">#{updateBy},</if>
+         </trim>
+    </insert>
+
+    <update id="updateFsPhysicalReportTemplate" parameterType="FsPhysicalReportTemplate">
+        update fs_physical_report_template
+        <trim prefix="SET" suffixOverrides=",">
+            <if test="templateName != null and templateName != ''">template_name = #{templateName},</if>
+            <if test="remark != null">remark = #{remark},</if>
+            <if test="createTime != null">create_time = #{createTime},</if>
+            <if test="updateTime != null">update_time = #{updateTime},</if>
+            <if test="status != null">status = #{status},</if>
+            <if test="createBy != null">create_by = #{createBy},</if>
+            <if test="updateBy != null">update_by = #{updateBy},</if>
+        </trim>
+        where id = #{id}
+    </update>
+
+    <delete id="deleteFsPhysicalReportTemplateById" parameterType="String">
+        delete from fs_physical_report_template where id = #{id}
+    </delete>
+
+    <delete id="deleteFsPhysicalReportTemplateByIds" parameterType="String">
+        delete from fs_physical_report_template where id in 
+        <foreach item="id" collection="array" open="(" separator="," close=")">
+            #{id}
+        </foreach>
+    </delete>
+</mapper>

+ 4 - 0
fs-service/src/main/resources/mapper/his/FsStoreProductAttrValueMapper.xml

@@ -134,4 +134,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         </foreach>
     </delete>
 
+    <select id="getFsStoreProductAttrValueListInProductId" resultType="com.fs.his.domain.FsStoreProductAttrValue">
+        select *,cost_price AS cost from fs_store_product_attr_value where product_id IN <foreach collection="productIds" index="index" item="item" open="(" separator="," close=")">#{item}</foreach>
+    </select>
+
 </mapper>

+ 10 - 1
fs-service/src/main/resources/mapper/his/FsStoreProductMapper.xml

@@ -47,7 +47,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
     </resultMap>
 
     <sql id="selectFsStoreProductVo">
-        select product_id,is_prescribe,is_drug, store_id, img_url, images, product_name, product_introduce, keyword, bar_code, cate_id, price, ot_price, unit_name, sort, sales, stock, is_show, is_hot, is_benefit, is_best, is_new, `desc`, create_time, update_time, is_postage, is_del, give_integral, cost_price, views, code_url, spec_type, product_type, prescribe_code, prescribe_spec, prescribe_factory, prescribe_name, is_display, temp_id from fs_store_product
+        select product_id,is_prescribe,is_drug, store_id, img_url, images, product_name, product_introduce, keyword, bar_code, cate_id, price, ot_price, unit_name, sort, sales, stock, is_show, is_hot, is_benefit, is_best, is_new, `desc`, create_time, update_time, is_postage, is_del, give_integral, cost_price, views, code_url, spec_type, product_type, prescribe_code, prescribe_spec, prescribe_factory, prescribe_name, is_display, temp_id,brand from fs_store_product
     </sql>
 
     <select id="selectFsStoreProductList" parameterType="FsStoreProduct" resultMap="FsStoreProductResult">
@@ -140,6 +140,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="tempId != null">temp_id,</if>
             <if test="isPrescribe != null">is_prescribe,</if>
             <if test="isDrug != null">is_drug,</if>
+            <if test="brand != null">brand,</if>
          </trim>
         <trim prefix="values (" suffix=")" suffixOverrides=",">
             <if test="storeId != null">#{storeId},</if>
@@ -180,6 +181,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="tempId != null">#{tempId},</if>
             <if test="isPrescribe != null">#{isPrescribe},</if>
             <if test="isDrug != null">#{isDrug},</if>
+            <if test="brand != null">#{brand},</if>
          </trim>
     </insert>
 
@@ -238,4 +240,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             #{productId}
         </foreach>
     </delete>
+
+    <select id="getStoreProductInProductIds" resultType="com.fs.his.domain.FsStoreProduct">
+        <include refid="selectFsStoreProductVo"/>
+        where product_id IN <foreach collection="productIds" index="index" item="item" open="(" separator="," close=")">
+        #{item}
+    </foreach>
+    </select>
 </mapper>

+ 10 - 0
fs-service/src/main/resources/mapper/qw/QwMaterialMapper.xml

@@ -54,6 +54,16 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         where material_id = #{materialId}
     </select>
 
+    <select id="selectQwMaterialListByMediaIdList"  resultMap="QwMaterialResult">
+        SELECT
+            material_id, material_type, material_media_id, created_at, material_name,
+            material_url, material_group_id, company_id, text_content, create_time,
+            title, title_url, update_time, create_user_id, send_count, group_type, corp_id
+        FROM qw_material
+        WHERE material_media_id IS NOT NULL
+        AND created_at &lt; UNIX_TIMESTAMP() - 48*3600;
+    </select>
+
     <insert id="insertQwMaterial" parameterType="QwMaterial">
         insert into qw_material
         <trim prefix="(" suffix=")" suffixOverrides=",">

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

@@ -68,6 +68,11 @@ public class FsStoreOrderController extends BaseController
     @Autowired
     @Qualifier("wdtErpOrderServiceImpl")
     private IErpOrderService wdtOrderService;
+
+    @Autowired
+    @Qualifier("JSTErpOrderServiceImpl")
+    private IErpOrderService jSTOrderService;
+
     /**
      * 查询订单列表
      */
@@ -343,7 +348,11 @@ public class FsStoreOrderController extends BaseController
                 } else if (erpType == 2){
                     //旺店通
                     erpOrderService =  wdtOrderService;
+                }else if (erpType == 5){
+                    //聚水潭
+                    erpOrderService =  jSTOrderService;
                 }
+
                 return erpOrderService;
 
 

+ 5 - 0
fs-user-app/src/main/java/com/fs/app/controller/course/CourseFsUserController.java

@@ -2,6 +2,7 @@ package com.fs.app.controller.course;
 
 
 
+import com.fs.app.annotation.UserOperationLog;
 import com.fs.app.controller.AppBaseController;
 import com.fs.common.annotation.RepeatSubmit;
 import com.fs.common.core.domain.R;
@@ -16,6 +17,7 @@ import com.fs.course.param.newfs.FsUserCourseVideoUParam;
 import com.fs.course.service.*;
 import com.fs.course.vo.FsUserCourseVideoH5VO;
 import com.fs.course.vo.newfs.FsUserCourseVideoLinkDetailsVO;
+import com.fs.his.enums.FsUserOperationEnum;
 import com.fs.his.service.IFsUserService;
 import com.fs.system.service.ISysConfigService;
 import io.swagger.annotations.Api;
@@ -68,6 +70,7 @@ public class CourseFsUserController extends AppBaseController {
     @Login
     @ApiOperation("H5课程详情")
     @GetMapping("/videoDetails")
+    @UserOperationLog(operationType = FsUserOperationEnum.STUDY)
     public ResponseResult<FsUserCourseVideoLinkDetailsVO> getCourseVideoDetails(FsUserCourseVideoLinkParam param) {
         param.setFsUserId(Long.parseLong(getUserId()));
         return courseVideoService.getLinkCourseVideoDetails(param);
@@ -99,6 +102,7 @@ public class CourseFsUserController extends AppBaseController {
 
     @ApiOperation("答题")
     @PostMapping("/courseAnswer")
+    @UserOperationLog(operationType = FsUserOperationEnum.ANSWER)
     public R courseAnswer(@RequestBody FsCourseQuestionAnswerUParam param){
         param.setUserId(Long.parseLong(getUserId()));
         logger.info("zyp \n【答题】:{}",param.getQuestions());
@@ -110,6 +114,7 @@ public class CourseFsUserController extends AppBaseController {
 
     @ApiOperation("发放奖励")
     @PostMapping("/sendReward")
+    @UserOperationLog(operationType = FsUserOperationEnum.SENDREWARD)
     @RepeatSubmit
     public R sendReward(@RequestBody FsCourseSendRewardUParam param)
     {

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

@@ -4,6 +4,7 @@ import cn.binarywang.wx.miniapp.api.WxMaService;
 import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
 import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo;
 import cn.hutool.core.date.DateTime;
+import com.fs.app.annotation.UserOperationLog;
 import com.fs.app.controller.AppBaseController;
 import com.fs.common.core.domain.R;
 import com.fs.common.core.redis.RedisCache;
@@ -19,6 +20,7 @@ import com.fs.core.config.WxMaConfiguration;
 import com.fs.app.utils.JwtUtils;
 import com.fs.his.domain.FsUser;
 import com.fs.his.domain.FsUserWx;
+import com.fs.his.enums.FsUserOperationEnum;
 import com.fs.his.service.IFsUserService;
 import com.fs.his.service.IFsUserWxService;
 import com.fs.system.mapper.SysConfigMapper;
@@ -77,7 +79,7 @@ public class CourseFsUserLoginController extends AppBaseController {
 
     @ApiOperation("小程序-授权登录")
     @PostMapping("/loginByMa")
-//    @UserOperationLog(operationType = FsUserOperationEnum.MINLOGIN)
+    @UserOperationLog(operationType = FsUserOperationEnum.MINLOGIN)
     public R login(@RequestBody LoginMaWxParam param) {
         log.info("=====================进入小程序授权登录, 入参: {}", param);
         if (StringUtils.isBlank(param.getCode())) {