Procházet zdrojové kódy

Merge branch 'master' of http://1.14.104.71:10880/root/ylrz_his_scrm_java

# Conflicts:
#	fs-service/src/main/java/com/fs/gtPush/service/impl/uniPush2ServiceImpl.java
#	fs-service/src/main/java/com/fs/gtPush/service/uniPush2Service.java
15376779826 před 1 měsícem
rodič
revize
1ddb0d510d
100 změnil soubory, kde provedl 3522 přidání a 131 odebrání
  1. 0 1
      fs-admin/src/main/java/com/fs/FSApplication.java
  2. 2 2
      fs-admin/src/main/java/com/fs/api/controller/IndexStatisticsController.java
  3. 1 0
      fs-admin/src/main/java/com/fs/company/controller/CompanyController.java
  4. 115 0
      fs-admin/src/main/java/com/fs/course/controller/FsCoursePlaySourceConfigController.java
  5. 13 0
      fs-admin/src/main/java/com/fs/course/controller/FsCourseProductOrderController.java
  6. 2 8
      fs-admin/src/main/java/com/fs/course/controller/FsCourseTrafficLogController.java
  7. 20 0
      fs-admin/src/main/java/com/fs/course/controller/FsCourseWatchCommentController.java
  8. 2 1
      fs-admin/src/main/java/com/fs/course/controller/FsUserCoursePeriodController.java
  9. 2 2
      fs-admin/src/main/java/com/fs/course/controller/FsUserWatchCourseStatisticsController.java
  10. 1 0
      fs-admin/src/main/java/com/fs/course/controller/qw/QwFsCourseWatchLogController.java
  11. 97 0
      fs-admin/src/main/java/com/fs/fastGpt/FastGptChatReplaceTextController.java
  12. 112 0
      fs-admin/src/main/java/com/fs/fastGpt/FastGptKeywordSendController.java
  13. 97 0
      fs-admin/src/main/java/com/fs/fastGpt/FastgptChatArtificialWordsController.java
  14. 139 0
      fs-admin/src/main/java/com/fs/fastGpt/FastgptEventLogTotalController.java
  15. 146 0
      fs-admin/src/main/java/com/fs/his/controller/FoodRecordController.java
  16. 23 4
      fs-admin/src/main/java/com/fs/his/controller/FsArticleCateController.java
  17. 6 0
      fs-admin/src/main/java/com/fs/his/controller/FsCityController.java
  18. 1 0
      fs-admin/src/main/java/com/fs/his/controller/FsCompanyController.java
  19. 106 0
      fs-admin/src/main/java/com/fs/his/controller/FsComplaintCategoryController.java
  20. 93 0
      fs-admin/src/main/java/com/fs/his/controller/FsComplaintController.java
  21. 7 2
      fs-admin/src/main/java/com/fs/his/controller/FsDoctorArticleController.java
  22. 106 0
      fs-admin/src/main/java/com/fs/his/controller/FsFirstDiagnosisController.java
  23. 103 0
      fs-admin/src/main/java/com/fs/his/controller/FsHfpayConfigController.java
  24. 52 0
      fs-admin/src/main/java/com/fs/his/controller/FsInquiryPatientInfoController.java
  25. 10 8
      fs-admin/src/main/java/com/fs/his/controller/FsPackageCateController.java
  26. 6 1
      fs-admin/src/main/java/com/fs/his/controller/FsStoreOrderController.java
  27. 3 1
      fs-admin/src/main/java/com/fs/his/controller/FsStorePaymentController.java
  28. 0 1
      fs-admin/src/main/java/com/fs/his/controller/FsStoreProductPackageController.java
  29. 120 0
      fs-admin/src/main/java/com/fs/his/controller/FsTodoItemsController.java
  30. 18 2
      fs-admin/src/main/java/com/fs/his/controller/FsUserController.java
  31. 102 0
      fs-admin/src/main/java/com/fs/his/controller/RechargeTemplateController.java
  32. 17 0
      fs-admin/src/main/java/com/fs/his/task/FsUserTask.java
  33. 229 4
      fs-admin/src/main/java/com/fs/his/task/Task.java
  34. 134 0
      fs-admin/src/main/java/com/fs/hisStore/FsStoreSCRMController.java
  35. 1 1
      fs-admin/src/main/java/com/fs/hisStore/controller/FsMaterialGroupScrmController.java
  36. 1 1
      fs-admin/src/main/java/com/fs/hisStore/controller/FsMaterialScrmController.java
  37. 1 1
      fs-admin/src/main/java/com/fs/hisStore/controller/FsMenuScrmController.java
  38. 1 1
      fs-admin/src/main/java/com/fs/hisStore/controller/FsPrescribeDrugScrmController.java
  39. 1 1
      fs-admin/src/main/java/com/fs/hisStore/controller/FsPrescribeScrmController.java
  40. 1 1
      fs-admin/src/main/java/com/fs/hisStore/controller/FsShippingTemplatesFreeScrmController.java
  41. 1 1
      fs-admin/src/main/java/com/fs/hisStore/controller/FsShippingTemplatesRegionScrmController.java
  42. 1 1
      fs-admin/src/main/java/com/fs/hisStore/controller/FsShippingTemplatesScrmController.java
  43. 2 2
      fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreActivityScrmController.java
  44. 1 1
      fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreAfterSalesItemScrmController.java
  45. 1 1
      fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreAfterSalesScrmController.java
  46. 1 1
      fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreAfterSalesStatusScrmController.java
  47. 1 1
      fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreCanvasScrmController.java
  48. 1 1
      fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreCartScrmController.java
  49. 2 2
      fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreCouponIssueScrmController.java
  50. 2 2
      fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreCouponIssueUserScrmController.java
  51. 2 2
      fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreCouponScrmController.java
  52. 2 2
      fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreCouponUserScrmController.java
  53. 62 7
      fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreHealthOrderScrmController.java
  54. 1 1
      fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreOrderAuditScrmController.java
  55. 1 1
      fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreOrderItemScrmController.java
  56. 1 1
      fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreOrderNoticeScrmController.java
  57. 1 1
      fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreOrderOfflineItemScrmController.java
  58. 1 1
      fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreOrderOfflineScrmController.java
  59. 1 1
      fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreOrderPromotionScrmController.java
  60. 26 11
      fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreOrderScrmController.java
  61. 1 1
      fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreOrderStatisticsScrmController.java
  62. 1 1
      fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreOrderStatusScrmController.java
  63. 1 1
      fs-admin/src/main/java/com/fs/hisStore/controller/FsStorePaymentScrmController.java
  64. 1 1
      fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreProductAttrScrmController.java
  65. 1 1
      fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreProductAttrValueScrmController.java
  66. 1 1
      fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreProductCategoryScrmController.java
  67. 1 1
      fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreProductDetailsScrmController.java
  68. 1 1
      fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreProductGroupScrmController.java
  69. 1 1
      fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreProductPackageScrmController.java
  70. 1 1
      fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreProductRelationScrmController.java
  71. 1 1
      fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreProductReplyScrmController.java
  72. 1 1
      fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreProductRuleScrmController.java
  73. 24 12
      fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreProductScrmController.java
  74. 1 1
      fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreProductTemplateScrmController.java
  75. 134 0
      fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreScrmController.java
  76. 1 1
      fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreShopScrmController.java
  77. 1 1
      fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreShopStaffScrmController.java
  78. 1 1
      fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreStatisticsScrmController.java
  79. 1 1
      fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreVisitScrmController.java
  80. 50 0
      fs-admin/src/main/java/com/fs/hisStore/controller/SysOperlogScrmController.java
  81. 1 1
      fs-admin/src/main/java/com/fs/hisStore/task/CrmTask.java
  82. 1 1
      fs-admin/src/main/java/com/fs/hisStore/task/ErpTask.java
  83. 92 5
      fs-admin/src/main/java/com/fs/hisStore/task/MallStoreTask.java
  84. 1 1
      fs-admin/src/main/java/com/fs/hisStore/task/stats/FsStatsMemberDailyTask.java
  85. 155 0
      fs-admin/src/main/java/com/fs/medical/MeasurementUnitController.java
  86. 157 0
      fs-admin/src/main/java/com/fs/medical/MedicalIndicatorController.java
  87. 160 0
      fs-admin/src/main/java/com/fs/medical/PhysicalExamReportController.java
  88. 190 0
      fs-admin/src/main/java/com/fs/medical/ReportIndicatorResultController.java
  89. 39 3
      fs-admin/src/main/java/com/fs/qw/controller/QwExternalContactController.java
  90. 1 1
      fs-admin/src/main/java/com/fs/qw/controller/QwSopTempController.java
  91. 82 0
      fs-admin/src/main/java/com/fs/saler/CompetitorInfoController.java
  92. 73 0
      fs-admin/src/main/java/com/fs/saler/FsServiceGoodsController.java
  93. 30 0
      fs-admin/src/main/java/com/fs/web/controller/system/SysConfigController.java
  94. 20 4
      fs-admin/src/main/java/com/fs/web/controller/system/SysLoginController.java
  95. 17 2
      fs-common/src/main/java/com/fs/common/annotation/Log.java
  96. 3 0
      fs-common/src/main/java/com/fs/common/core/redis/RedisCache.java
  97. 23 0
      fs-common/src/main/java/com/fs/common/utils/CloudHostUtils.java
  98. 42 0
      fs-common/src/main/java/com/fs/common/utils/DateUtils.java
  99. 3 0
      fs-common/src/main/java/com/fs/common/utils/DictUtils.java
  100. 205 0
      fs-common/src/main/java/com/fs/common/utils/FileNameExtractor.java

+ 0 - 1
fs-admin/src/main/java/com/fs/FSApplication.java

@@ -14,7 +14,6 @@ import org.springframework.transaction.annotation.Transactional;
  * 启动程序
  */
 @SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })
-@Transactional
 @EnableAsync
 @EnableScheduling
 public class FSApplication

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

@@ -64,10 +64,10 @@ public class IndexStatisticsController {
     @GetMapping("/trafficLog")
     public R getTrafficLog(){
         TrafficLogDTO trafficLogDTO = redisCache.getCacheObject(DATA_OVERVIEW_TRAFFIC_LOG);
-        if(trafficLogDTO == null) {
+        SysConfig sysConfig = sysConfigService.selectConfigByConfigKey("redPacket.Traffic.config");
+        if(trafficLogDTO == null || sysConfig == null) {
             return null;
         }
-        SysConfig sysConfig = sysConfigService.selectConfigByConfigKey("redPacket.Traffic.config");
         String configValue = sysConfig.getConfigValue();
         trafficLogDTO.setTraffic(configValue);
         return R.ok().put("data",trafficLogDTO);

+ 1 - 0
fs-admin/src/main/java/com/fs/company/controller/CompanyController.java

@@ -132,6 +132,7 @@ public class CompanyController extends BaseController
                 callerService.updateCompanyVoiceCaller(caller);
             }
         }
+        company.setUpdateMiniApp(true);
         return toAjax(companyService.updateCompany(company));
     }
 

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

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

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

@@ -69,6 +69,19 @@ public class FsCourseProductOrderController extends BaseController
         return util.exportExcel(list, "拍单商品订单数据");
     }
 
+    /**
+     * 导出拍单商品订单列表
+     */
+    @PreAuthorize("@ss.hasPermi('course:fsCourseProductOrder:decodeExport')")
+    @Log(title = "拍单商品订单", businessType = BusinessType.EXPORT)
+    @GetMapping("/decodeExport")
+    public AjaxResult decodeExport(FsCourseProductOrderListParam param)
+    {
+        List<FsCourseProductOrderVO> list = fsCourseProductOrderService.selectFsCourseProductOrderDecodePhoneList(param);
+        ExcelUtil<FsCourseProductOrderVO> util = new ExcelUtil<FsCourseProductOrderVO>(FsCourseProductOrderVO.class);
+        return util.exportExcel(list, "拍单商品订单数据");
+    }
+
     /**
      * 获取拍单商品订单详细信息
      */

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

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

+ 20 - 0
fs-admin/src/main/java/com/fs/course/controller/FsCourseWatchCommentController.java

@@ -70,6 +70,14 @@ public class FsCourseWatchCommentController extends BaseController
         return util.exportExcel(list, "看课评论数据");
     }
 
+    @PreAuthorize("@ss.hasPermi('course:courseWatchComment:edit')")
+    @Log(title = "看课评论", businessType = BusinessType.UPDATE)
+    @PutMapping("/updateBarrageStatus")
+    public AjaxResult updateBarrageStatus(@RequestBody FsCourseWatchComment fsCourseWatchComment)
+    {
+        return toAjax(fsCourseWatchCommentService.updateFsCourseWatchComment(fsCourseWatchComment));
+    }
+
     /**
      * 获取看课评论详细信息
      */
@@ -125,4 +133,16 @@ public class FsCourseWatchCommentController extends BaseController
         }
     }
 
+    @Log(title = "手动解除外部联系人拉黑用户", businessType = BusinessType.UPDATE)
+    @PutMapping("/clearBlack")
+    public R clearBlack(Integer commentStatus, Long fsUserId)
+    {
+        int i = qwExternalContactService.updateQwExternalContactByFsUserId(commentStatus, fsUserId);
+        if (i > 0){
+            return R.ok();
+        } else {
+            return R.error();
+        }
+    }
+
 }

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

@@ -220,10 +220,11 @@ public class FsUserCoursePeriodController extends BaseController {
     public R periodCourseCount(@RequestBody PeriodCountParam param) {
         PageHelper.startPage(param.getPageNum(), param.getPageSize());
         List<FsPeriodCountVO> list = fsUserCoursePeriodDaysService.periodCourseCount(param);
+        long count = fsUserCoursePeriodDaysService.periodCourseByCount(param);
         PageInfo<FsPeriodCountVO> pageInfo = new PageInfo<>(list);
         Map<String, Object> result = new HashMap<>();
         result.put("rows", pageInfo.getList());
-        result.put("total", pageInfo.getTotal());
+        result.put("total", count);
         return R.ok(result);
     }
 

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

@@ -118,9 +118,9 @@ public class FsUserWatchCourseStatisticsController extends BaseController
     }
 
     /**
-     * 导出会员看课统计-按课程汇总统计列表
+     * 导出会员观看数据明细汇总
      */
-    @Log(title = "会员看课统计-按课程汇总统计", businessType = BusinessType.EXPORT)
+    @Log(title = "会员观看数据明细汇总", businessType = BusinessType.EXPORT)
     @GetMapping("/exportTotal")
     public AjaxResult exportTotal(FsUserWatchCourseStatistics fsUserWatchCourseStatistics)
     {

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

@@ -71,6 +71,7 @@ public class QwFsCourseWatchLogController extends BaseController
         if (param.getSTime()==null||param.getETime()==null){
             return getDataTable(new ArrayList<>());
         }
+        param.setSendType(2); //企微
         List<FsCourseWatchLogStatisticsListVO> list = fsCourseWatchLogService.selectFsCourseWatchLogStatisticsListVO(param);
         return getDataTable(list);
     }

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

@@ -0,0 +1,97 @@
+package com.fs.fastGpt;
+
+import com.fs.common.annotation.Log;
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.core.page.TableDataInfo;
+import com.fs.common.enums.BusinessType;
+import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.fastGpt.domain.FastGptChatReplaceText;
+import com.fs.fastGpt.service.IFastGptChatReplaceTextService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * 易错词语Controller
+ *
+ * @author fs
+ * @date 2025-01-18
+ */
+@RestController
+@RequestMapping("/fastGpt/fastGptChatReplaceText")
+public class FastGptChatReplaceTextController extends BaseController
+{
+    @Autowired
+    private IFastGptChatReplaceTextService fastGptChatReplaceTextService;
+
+    /**
+     * 查询易错词语列表
+     */
+    @PreAuthorize("@ss.hasPermi('fastGpt:fastGptChatReplaceText:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(FastGptChatReplaceText fastGptChatReplaceText)
+    {
+        startPage();
+        List<FastGptChatReplaceText> list = fastGptChatReplaceTextService.selectFastGptChatReplaceTextList(fastGptChatReplaceText);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出易错词语列表
+     */
+    @PreAuthorize("@ss.hasPermi('fastGpt:fastGptChatReplaceText:export')")
+    @Log(title = "易错词语", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(FastGptChatReplaceText fastGptChatReplaceText)
+    {
+        List<FastGptChatReplaceText> list = fastGptChatReplaceTextService.selectFastGptChatReplaceTextList(fastGptChatReplaceText);
+        ExcelUtil<FastGptChatReplaceText> util = new ExcelUtil<FastGptChatReplaceText>(FastGptChatReplaceText.class);
+        return util.exportExcel(list, "易错词语数据");
+    }
+
+    /**
+     * 获取易错词语详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('fastGpt:fastGptChatReplaceText:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id)
+    {
+        return AjaxResult.success(fastGptChatReplaceTextService.selectFastGptChatReplaceTextById(id));
+    }
+
+    /**
+     * 新增易错词语
+     */
+    @PreAuthorize("@ss.hasPermi('fastGpt:fastGptChatReplaceText:add')")
+    @Log(title = "易错词语", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody FastGptChatReplaceText fastGptChatReplaceText)
+    {
+        return toAjax(fastGptChatReplaceTextService.insertFastGptChatReplaceText(fastGptChatReplaceText));
+    }
+
+    /**
+     * 修改易错词语
+     */
+    @PreAuthorize("@ss.hasPermi('fastGpt:fastGptChatReplaceText:edit')")
+    @Log(title = "易错词语", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody FastGptChatReplaceText fastGptChatReplaceText)
+    {
+        return toAjax(fastGptChatReplaceTextService.updateFastGptChatReplaceText(fastGptChatReplaceText));
+    }
+
+    /**
+     * 删除易错词语
+     */
+    @PreAuthorize("@ss.hasPermi('fastGpt:fastGptChatReplaceText:remove')")
+    @Log(title = "易错词语", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids)
+    {
+        return toAjax(fastGptChatReplaceTextService.deleteFastGptChatReplaceTextByIds(ids));
+    }
+}

+ 112 - 0
fs-admin/src/main/java/com/fs/fastGpt/FastGptKeywordSendController.java

@@ -0,0 +1,112 @@
+package com.fs.fastGpt;
+
+import com.fs.common.annotation.Log;
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.core.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.fastGpt.domain.FastGptKeyword;
+import com.fs.fastGpt.domain.FastGptKeywordSend;
+import com.fs.fastGpt.service.IFastGptKeywordSendService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * Ai事件表(根据关键字发送文本和图片)Controller
+ * 
+ * @author fs
+ * @date 2025-05-12
+ */
+@RestController
+@RequestMapping("/fastGpt/fastGptKeywordSend")
+public class FastGptKeywordSendController extends BaseController
+{
+    @Autowired
+    private IFastGptKeywordSendService fastGptKeywordSendService;
+
+    @GetMapping("/keywordList")
+    public R keywordList()
+    {
+        List<FastGptKeyword> list = fastGptKeywordSendService.selectFastGptKeywordList(1);
+        return R.ok().put("data",list);
+    }
+    /**
+     * 查询Ai事件表(根据关键字发送文本和图片)列表
+     */
+    @PreAuthorize("@ss.hasPermi('fastGpt:fastGptKeywordSend:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(FastGptKeywordSend fastGptKeywordSend)
+    {
+        startPage();
+        fastGptKeywordSend.setKeywordType(1L);
+        List<FastGptKeywordSend> list = fastGptKeywordSendService.selectFastGptKeywordSendList(fastGptKeywordSend);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出Ai事件表(根据关键字发送文本和图片)列表
+     */
+    @PreAuthorize("@ss.hasPermi('fastGpt:fastGptKeywordSend:export')")
+    @Log(title = "Ai事件表(根据关键字发送文本和图片)", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(FastGptKeywordSend fastGptKeywordSend)
+    {
+        fastGptKeywordSend.setKeywordType(1L);
+        List<FastGptKeywordSend> list = fastGptKeywordSendService.selectFastGptKeywordSendList(fastGptKeywordSend);
+        ExcelUtil<FastGptKeywordSend> util = new ExcelUtil<FastGptKeywordSend>(FastGptKeywordSend.class);
+        return util.exportExcel(list, "Ai事件表(根据关键字发送文本和图片)数据");
+    }
+
+    /**
+     * 获取Ai事件表(根据关键字发送文本和图片)详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('fastGpt:fastGptKeywordSend:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id)
+    {
+        Long keywordType = 1L;
+        return AjaxResult.success(fastGptKeywordSendService.selectFastGptKeywordSendById(id,keywordType));
+    }
+
+    /**
+     * 新增Ai事件表(根据关键字发送文本和图片)
+     */
+    @PreAuthorize("@ss.hasPermi('fastGpt:fastGptKeywordSend:add')")
+    @Log(title = "Ai事件表(根据关键字发送文本和图片)", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody FastGptKeywordSend fastGptKeywordSend)
+    {
+        fastGptKeywordSend.setKeywordType(1L);
+        fastGptKeywordSend.setRoleIds(null);
+        return toAjax(fastGptKeywordSendService.insertFastGptKeywordSend(fastGptKeywordSend));
+    }
+
+    /**
+     * 修改Ai事件表(根据关键字发送文本和图片)
+     */
+    @PreAuthorize("@ss.hasPermi('fastGpt:fastGptKeywordSend:edit')")
+    @Log(title = "Ai事件表(根据关键字发送文本和图片)", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody FastGptKeywordSend fastGptKeywordSend)
+    {
+        fastGptKeywordSend.setKeywordType(1L);
+        fastGptKeywordSend.setRoleIds(null);
+        return toAjax(fastGptKeywordSendService.updateFastGptKeywordSend(fastGptKeywordSend));
+    }
+
+    /**
+     * 删除Ai事件表(根据关键字发送文本和图片)
+     */
+    @PreAuthorize("@ss.hasPermi('fastGpt:fastGptKeywordSend:remove')")
+    @Log(title = "Ai事件表(根据关键字发送文本和图片)", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids)
+    {
+        return toAjax(fastGptKeywordSendService.deleteFastGptKeywordSendByIds(ids));
+    }
+}

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

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

+ 139 - 0
fs-admin/src/main/java/com/fs/fastGpt/FastgptEventLogTotalController.java

@@ -0,0 +1,139 @@
+package com.fs.fastGpt;
+
+import com.fs.common.annotation.Log;
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.core.domain.R;
+import com.fs.common.enums.BusinessType;
+import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.fastGpt.domain.FastgptEventLogTotal;
+import com.fs.fastGpt.param.FastgptEventLogTotalParam;
+import com.fs.fastGpt.service.IFastGptRoleService;
+import com.fs.fastGpt.service.IFastgptEventLogTotalService;
+import com.fs.fastGpt.vo.FastgptEventLogTotalVo;
+import com.github.pagehelper.PageInfo;
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * ai事件埋点统计Controller
+ * 
+ * @author fs
+ * @date 2025-06-26
+ */
+@RestController
+@RequestMapping("/fastGpt/fastgptEventLogTotal")
+public class FastgptEventLogTotalController extends BaseController
+{
+    @Autowired
+    private IFastgptEventLogTotalService fastgptEventLogTotalService;
+
+    @Autowired
+    private IFastGptRoleService roleService;
+
+    /**
+     * 查询ai事件埋点统计列表
+     */
+    @PreAuthorize("@ss.hasPermi('fastGpt:fastgptEventLogTotal:list')")
+    @PostMapping("/list")
+    public R pageList(@RequestBody FastgptEventLogTotalParam param)
+    {
+        FastgptEventLogTotalVo eventLogTotalVo = new FastgptEventLogTotalVo();
+        BeanUtils.copyProperties(param,eventLogTotalVo);
+        List<FastgptEventLogTotalVo> list = fastgptEventLogTotalService.selectFastgptEventLogTotalVoInfoList(eventLogTotalVo);
+
+        //统计对应的list的合
+        FastgptEventLogTotalVo totalVo = fastgptEventLogTotalService.totalFastgptEventLog(list);
+
+        int pageNum = param.getPageNum();
+        int pageSize = param.getPageSize();
+
+        int total = 0;
+        if (list != null) {
+            total = list.size();
+        }
+
+        int fromIndex = (pageNum - 1) * pageSize;
+        int toIndex = Math.min(fromIndex + pageSize, total);
+        PageInfo<FastgptEventLogTotalVo> pageInfo = new PageInfo<>();
+        if (list != null) {
+            List<FastgptEventLogTotalVo> paginatedList = list.subList(fromIndex, toIndex);
+            if(totalVo != null){
+                paginatedList.add(totalVo);
+            }
+            pageInfo = new PageInfo<>(paginatedList);
+        }else{
+            pageInfo = new PageInfo<>();
+        }
+        pageInfo.setTotal(total);
+        return R.ok().put("data",pageInfo);
+    }
+
+    /**
+     * 查询appKey
+     * @return  list
+     */
+    @GetMapping("/getFastGptRoleAppKeyList")
+    public R getFastGptRoleAppKeyList() {
+        return R.ok().put("data", roleService.selectFastGptRoleAppKeyList());
+    }
+    /**
+     * 导出ai事件埋点统计列表
+     */
+    @PreAuthorize("@ss.hasPermi('fastGpt:fastgptEventLogTotal:export')")
+    @Log(title = "ai事件埋点统计", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(FastgptEventLogTotal fastgptEventLogTotal)
+    {
+        List<FastgptEventLogTotal> list = fastgptEventLogTotalService.selectFastgptEventLogTotalList(fastgptEventLogTotal);
+        ExcelUtil<FastgptEventLogTotal> util = new ExcelUtil<FastgptEventLogTotal>(FastgptEventLogTotal.class);
+        return util.exportExcel(list, "ai事件埋点统计数据");
+    }
+
+    /**
+     * 获取ai事件埋点统计详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('fastGpt:fastgptEventLogTotal:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id)
+    {
+        return AjaxResult.success(fastgptEventLogTotalService.selectFastgptEventLogTotalById(id));
+    }
+
+    /**
+     * 新增ai事件埋点统计
+     */
+    @PreAuthorize("@ss.hasPermi('fastGpt:fastgptEventLogTotal:add')")
+    @Log(title = "ai事件埋点统计", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody FastgptEventLogTotal fastgptEventLogTotal)
+    {
+        return toAjax(fastgptEventLogTotalService.insertFastgptEventLogTotal(fastgptEventLogTotal));
+    }
+
+    /**
+     * 修改ai事件埋点统计
+     */
+    @PreAuthorize("@ss.hasPermi('fastGpt:fastgptEventLogTotal:edit')")
+    @Log(title = "ai事件埋点统计", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody FastgptEventLogTotal fastgptEventLogTotal)
+    {
+        return toAjax(fastgptEventLogTotalService.updateFastgptEventLogTotal(fastgptEventLogTotal));
+    }
+
+    /**
+     * 删除ai事件埋点统计
+     */
+    @PreAuthorize("@ss.hasPermi('fastGpt:fastgptEventLogTotal:remove')")
+    @Log(title = "ai事件埋点统计", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids)
+    {
+        return toAjax(fastgptEventLogTotalService.deleteFastgptEventLogTotalByIds(ids));
+    }
+}

+ 146 - 0
fs-admin/src/main/java/com/fs/his/controller/FoodRecordController.java

@@ -0,0 +1,146 @@
+package com.fs.his.controller;
+
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.R;
+import com.fs.common.core.page.TableDataInfo;
+import com.fs.common.utils.StringUtils;
+import com.fs.foods.domain.FsFoodRecord;
+import com.fs.foods.param.FoodRecordAddParam;
+import com.fs.foods.param.FoodRecordEditParam;
+import com.fs.foods.param.FoodRecordQueryParam;
+import com.fs.foods.service.IFsFoodRecordService;
+import com.fs.his.mapper.FsUserMapper;
+import com.fs.store.service.cache.IFsUserCacheService;
+import com.github.pagehelper.PageHelper;
+import com.github.pagehelper.PageInfo;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.validation.Valid;
+import java.util.List;
+
+/**
+ * 饮食记录控制器
+ */
+@Api("饮食记录管理")
+@RestController
+@Slf4j
+@RequestMapping(value = "/food-record")
+public class FoodRecordController extends BaseController {
+
+    @Autowired
+    private IFsFoodRecordService foodRecordService;
+
+    /**
+     * 获取用户饮食记录详情
+     */
+    @ApiOperation("获取饮食记录详情")
+    @GetMapping("/getRecordInfo/{id}")
+    public R getRecordInfo(@PathVariable Long id, HttpServletRequest request) {
+        FsFoodRecord record = foodRecordService.selectFsFoodRecordById(id);
+        return R.ok().put("data",record);
+    }
+
+
+    /**
+     * 获取用户饮食记录分页列表
+     */
+    @ApiOperation("获取用户饮食记录列表")
+    @GetMapping("/getMyRecordList")
+    public R getMyRecordList(FoodRecordQueryParam param, HttpServletRequest request) {
+        try {
+            PageHelper.startPage(param.getPageNum(), param.getPageSize());
+            List<FsFoodRecord> list = foodRecordService.selectFoodRecordList(param);
+            PageInfo<FsFoodRecord> listPageInfo = new PageInfo<>(list);
+            return R.ok().put("data", listPageInfo);
+        } catch (Exception e) {
+            log.error("获取饮食记录列表异常:", e);
+            return R.error("操作异常");
+        }
+    }
+
+    /**
+     * 新增饮食记录
+     */
+    @ApiOperation("新增饮食记录")
+    @PostMapping("/addRecord")
+    public R addRecord(@RequestBody @Valid FoodRecordAddParam param, HttpServletRequest request) {
+        try {
+            log.info("【新增饮食记录】:{}", param);
+
+            if (StringUtils.isEmpty(param.getMealDescription())) {
+                return R.error("用餐描述不能为空");
+            }
+
+            FsFoodRecord record = new FsFoodRecord();
+            BeanUtils.copyProperties(param, record);
+
+            if (foodRecordService.insertFsFoodRecord(record) > 0) {
+                return R.ok("添加成功");
+            } else {
+                return R.error("添加失败");
+            }
+        } catch (Exception e) {
+            log.error("新增饮食记录异常:", e);
+            return R.error("操作异常");
+        }
+    }
+
+    /**
+     * 修改饮食记录
+     */
+    @ApiOperation("修改饮食记录")
+    @PostMapping("/editRecord")
+    public R editRecord(@RequestBody @Valid FoodRecordEditParam param, HttpServletRequest request) {
+        try {
+            log.info("【修改饮食记录】:{}", param);
+
+            FsFoodRecord record = new FsFoodRecord();
+            BeanUtils.copyProperties(param, record);
+
+            if (foodRecordService.updateFsFoodRecord(record) > 0) {
+                return R.ok("修改成功");
+            } else {
+                return R.error("修改失败");
+            }
+        } catch (Exception e) {
+            log.error("修改饮食记录异常:", e);
+            return R.error("操作异常");
+        }
+    }
+
+    /**
+     * 删除饮食记录
+     */
+    @ApiOperation("删除饮食记录")
+    @PostMapping("/deleteRecord/{id}")
+    public R deleteRecord(@PathVariable("id") Long id, HttpServletRequest request) {
+        foodRecordService.deleteFsFoodRecordById(id);
+        return R.ok();
+    }
+
+
+    @Autowired
+    private IFsUserCacheService fsUserCacheService;
+    /**
+     * 管理端查询饮食记录列表
+     */
+    @ApiOperation("管理端查询饮食记录")
+    @GetMapping("/admin/list")
+    public TableDataInfo adminList(FoodRecordQueryParam param) {
+        startPage();
+        List<FsFoodRecord> list = foodRecordService.selectFoodRecordList(param);
+        for (FsFoodRecord fsFoodRecord : list) {
+            String fsUserName = fsUserCacheService.selectUserNameById(fsFoodRecord.getUserId());
+            if(StringUtils.isNotEmpty(fsUserName)){
+                fsFoodRecord.setUsername(fsUserName);
+            }
+        }
+        return getDataTable(list);
+    }
+}

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

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

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

@@ -129,4 +129,10 @@ public class FsCityController extends BaseController
         return R.ok().put("data",fsCityService.getCitysArea());
     }
 
+    @GetMapping("/getAllList")
+    public R getAllList(FsCity fsCity)
+    {
+        List<FsCity> list = fsCityService.selectFsCityList(fsCity);
+        return R.ok().put("data",list);
+    }
 }

+ 1 - 0
fs-admin/src/main/java/com/fs/his/controller/FsCompanyController.java

@@ -145,6 +145,7 @@ public class FsCompanyController extends BaseController
     public AjaxResult edit(@RequestBody Company company)
     {
         company.setMoney(null);
+        company.setUpdateMiniApp(true);
         return toAjax(companyService.updateCompany(company));
     }
 

+ 106 - 0
fs-admin/src/main/java/com/fs/his/controller/FsComplaintCategoryController.java

@@ -0,0 +1,106 @@
+package com.fs.his.controller;
+
+import com.fs.common.annotation.Log;
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.R;
+import com.fs.common.core.page.TableDataInfo;
+import com.fs.common.enums.BusinessType;
+import com.fs.complaint.domain.FsComplaintCategory;
+import com.fs.complaint.mapper.FsComplaintCategoryMapper;
+import com.fs.complaint.param.FsComplaintCategoryParam;
+import com.fs.complaint.service.FsComplaintCategoryService;
+import com.fs.complaint.vo.FsComplaintCategoryListVO;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+@Slf4j
+@Api("投诉接口")
+@RestController
+@RequestMapping(value="/complaint")
+public class FsComplaintCategoryController extends BaseController {
+
+    @Autowired
+    private FsComplaintCategoryMapper fsComplaintCategoryMapper;
+
+    @Autowired
+    private FsComplaintCategoryService fsComplaintCategoryService;
+
+
+    /**
+     * 查询投诉分类列表
+     */
+    @ApiOperation("查询投诉分类列表")
+    @PreAuthorize("@ss.hasPermi('complaint:category:list')")
+    @GetMapping("/category/list")
+    public TableDataInfo list(FsComplaintCategoryParam param)
+    {
+        startPage();
+        List<FsComplaintCategoryListVO> list = fsComplaintCategoryMapper.selectFsComplaintCategoryListVO(param);
+        return getDataTable(list);
+    }
+    /**
+     * 根据ID查询投诉分类详情
+     */
+    @ApiOperation("查询投诉分类详情")
+    @PreAuthorize("@ss.hasPermi('complaint:category:query')")
+    @GetMapping("/category/{id}")
+    public R getInfo(@PathVariable("id") Long id)
+    {
+        return R.ok().put("data",fsComplaintCategoryService.selectFsComplaintCategoryById(id));
+    }
+
+    /**
+     * 新增投诉分类
+     */
+    @ApiOperation("新增投诉分类")
+    @PreAuthorize("@ss.hasPermi('complaint:category:add')")
+    @Log(title = "投诉分类", businessType = BusinessType.INSERT)
+    @PostMapping("/category")
+    public R add(@RequestBody FsComplaintCategory fsComplaintCategory)
+    {
+        fsComplaintCategoryService.insertFsComplaintCategory(fsComplaintCategory);
+        return R.ok();
+    }
+    @ApiOperation("修改投诉分类")
+    @PreAuthorize("@ss.hasPermi('complaint:category:edit')")
+    @Log(title = "投诉分类", businessType = BusinessType.UPDATE)
+    @PutMapping("/category")
+    public R edit(@RequestBody FsComplaintCategory fsComplaintCategory)
+    {
+        log.info("修改投诉分类 参数:{}",fsComplaintCategory);
+        fsComplaintCategoryService.updateFsComplaintCategory(fsComplaintCategory);
+        return R.ok();
+    }
+    /**
+     * 删除投诉分类
+     */
+    @ApiOperation("删除投诉分类")
+    @PreAuthorize("@ss.hasPermi('complaint:category:remove')")
+    @Log(title = "投诉分类", businessType = BusinessType.DELETE)
+    @DeleteMapping("/category/{ids}")
+    public R remove(@PathVariable Long[] ids)
+    {
+        fsComplaintCategoryService.deleteFsComplaintCategoryByIds(ids);
+        return R.ok();
+    }
+    /**
+     * 修改投诉分类状态
+     */
+    @ApiOperation("修改投诉分类状态")
+    @PreAuthorize("@ss.hasPermi('complaint:category:edit')")
+    @Log(title = "投诉分类状态", businessType = BusinessType.UPDATE)
+    @PutMapping("/category/status")
+    public R changeStatus(@RequestBody FsComplaintCategory fsComplaintCategory)
+    {
+        log.info("投诉分类状态 参数:{}",fsComplaintCategory);
+        fsComplaintCategoryService.updateFsComplaintCategoryStatus(fsComplaintCategory);
+        return R.ok();
+    }
+
+}

+ 93 - 0
fs-admin/src/main/java/com/fs/his/controller/FsComplaintController.java

@@ -0,0 +1,93 @@
+package com.fs.his.controller;
+
+import com.fs.common.annotation.Log;
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.R;
+import com.fs.common.core.page.TableDataInfo;
+import com.fs.common.enums.BusinessType;
+import com.fs.complaint.domain.FsComplaint;
+import com.fs.complaint.domain.FsComplaintCategory;
+import com.fs.complaint.dto.ComplaintQueryDTO;
+import com.fs.complaint.dto.SubmitComplaintDTO;
+import com.fs.complaint.dto.UpdateComplaintDTO;
+import com.fs.complaint.mapper.FsComplaintCategoryMapper;
+import com.fs.complaint.mapper.FsComplaintMapper;
+import com.fs.complaint.param.FsComplaintCategoryParam;
+import com.fs.complaint.service.FsComplaintCategoryService;
+import com.fs.complaint.service.FsComplaintService;
+import com.fs.complaint.vo.ComplaintVO;
+import com.fs.complaint.vo.FsComplaintCategoryListVO;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+import shade.kotlin.Result;
+
+import javax.validation.Valid;
+import java.util.List;
+
+@Slf4j
+@Api("投诉接口")
+@RestController
+@RequestMapping(value="/complaint")
+public class FsComplaintController extends BaseController {
+
+    @Autowired
+    private FsComplaintService fsComplaintService;
+    @Autowired
+    private FsComplaintCategoryService fsComplaintCategoryService;
+
+    /**
+     * 查询所有投诉分类
+     * @return R
+     */
+    @PostMapping("/queryAllCategory")
+    public R queryAllCategory(){
+        List<FsComplaintCategory> categoryList = fsComplaintCategoryService.queryAllCategory();
+        return R.ok().put("data",categoryList);
+    }
+
+    @ApiOperation("提交投诉")
+    @PostMapping
+    public R submitComplaint(@Valid @RequestBody SubmitComplaintDTO dto) {
+        fsComplaintService.submitComplaint(dto);
+        return R.ok();
+    }
+
+    @ApiOperation("根据ID查询投诉详情")
+    @GetMapping("/{id}")
+    public R getComplaintById(@PathVariable Long id) {
+        ComplaintVO complaintVO = fsComplaintService.getComplaintById(id);
+        return R.ok().put("data", complaintVO);
+    }
+    @ApiOperation("根据投诉单号查询投诉详情")
+    @GetMapping("/no/{complaintNo}")
+    public R getComplaintByNo(@PathVariable String complaintNo) {
+        ComplaintVO complaintVO = fsComplaintService.getComplaintByNo(complaintNo);
+        return R.ok().put("data", complaintVO);
+    }
+    @ApiOperation("分页查询投诉列表")
+    @PostMapping("/list")
+    public TableDataInfo getComplaintPage(@RequestBody ComplaintQueryDTO queryDTO) {
+        startPage();
+
+        List<FsComplaint> result = fsComplaintService.getComplaintPage(queryDTO);
+
+        return getDataTable(result);
+    }
+    @ApiOperation("更新投诉信息")
+    @PutMapping("/{id}")
+    public R updateComplaint(@PathVariable Long id, @Valid @RequestBody UpdateComplaintDTO dto) {
+        fsComplaintService.updateComplaint(id, dto);
+        return R.ok();
+    }
+    @ApiOperation("删除投诉")
+    @DeleteMapping("/{id}")
+    public R deleteComplaint(@PathVariable Long id) {
+        fsComplaintService.deleteComplaint(id);
+        return R.ok();
+    }
+
+}

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

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

+ 106 - 0
fs-admin/src/main/java/com/fs/his/controller/FsFirstDiagnosisController.java

@@ -0,0 +1,106 @@
+package com.fs.his.controller;
+
+import java.util.List;
+
+import com.fs.his.param.FsFirstDiagnosisParam;
+import com.fs.his.vo.FsFirstDiagnosisVO;
+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.FsFirstDiagnosis;
+import com.fs.his.service.IFsFirstDiagnosisService;
+import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.common.core.page.TableDataInfo;
+
+/**
+ * 初诊单Controller
+ * 
+ * @author fs
+ * @date 2025-09-01
+ */
+@RestController
+@RequestMapping("/his/fsFirstDiagnosis")
+public class FsFirstDiagnosisController extends BaseController
+{
+    @Autowired
+    private IFsFirstDiagnosisService fsFirstDiagnosisService;
+
+    /**
+     * 查询初诊单列表
+     */
+    @PreAuthorize("@ss.hasPermi('his:fsFirstDiagnosis:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(FsFirstDiagnosisParam fsFirstDiagnosis)
+    {
+        startPage();
+        List<FsFirstDiagnosisVO> list = fsFirstDiagnosisService.selectFsFirstDiagnosisVOList(fsFirstDiagnosis);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出初诊单列表
+     */
+    @PreAuthorize("@ss.hasPermi('his:fsFirstDiagnosis:export')")
+    @Log(title = "初诊单", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(FsFirstDiagnosisParam fsFirstDiagnosis)
+    {
+        List<FsFirstDiagnosisVO> list = fsFirstDiagnosisService.selectFsFirstDiagnosisVOList(fsFirstDiagnosis);
+        ExcelUtil<FsFirstDiagnosisVO> util = new ExcelUtil<FsFirstDiagnosisVO>(FsFirstDiagnosisVO.class);
+        return util.exportExcel(list, "初诊单数据");
+    }
+
+    /**
+     * 获取初诊单详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('his:fsFirstDiagnosis:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id)
+    {
+        return AjaxResult.success(fsFirstDiagnosisService.selectFsFirstDiagnosisById(id));
+    }
+
+    /**
+     * 新增初诊单
+     */
+    @PreAuthorize("@ss.hasPermi('his:fsFirstDiagnosis:add')")
+    @Log(title = "初诊单", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody FsFirstDiagnosis fsFirstDiagnosis)
+    {
+        return toAjax(fsFirstDiagnosisService.insertFsFirstDiagnosis(fsFirstDiagnosis));
+    }
+
+    /**
+     * 修改初诊单
+     */
+    @PreAuthorize("@ss.hasPermi('his:fsFirstDiagnosis:edit')")
+    @Log(title = "初诊单", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody FsFirstDiagnosis fsFirstDiagnosis)
+    {
+        return toAjax(fsFirstDiagnosisService.updateFsFirstDiagnosis(fsFirstDiagnosis));
+    }
+
+    /**
+     * 删除初诊单
+     */
+    @PreAuthorize("@ss.hasPermi('his:fsFirstDiagnosis:remove')")
+    @Log(title = "初诊单", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids)
+    {
+        return toAjax(fsFirstDiagnosisService.deleteFsFirstDiagnosisByIds(ids));
+    }
+}

+ 103 - 0
fs-admin/src/main/java/com/fs/his/controller/FsHfpayConfigController.java

@@ -0,0 +1,103 @@
+package com.fs.his.controller;
+
+import java.util.List;
+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.FsHfpayConfig;
+import com.fs.his.service.IFsHfpayConfigService;
+import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.common.core.page.TableDataInfo;
+
+/**
+ * 汇付多支付配置Controller
+ * 
+ * @author fs
+ * @date 2025-09-10
+ */
+@RestController
+@RequestMapping("/his/hfpayConfig")
+public class FsHfpayConfigController extends BaseController
+{
+    @Autowired
+    private IFsHfpayConfigService fsHfpayConfigService;
+
+    /**
+     * 查询汇付多支付配置列表
+     */
+    @PreAuthorize("@ss.hasPermi('his:hfpayConfig:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(FsHfpayConfig fsHfpayConfig)
+    {
+        startPage();
+        List<FsHfpayConfig> list = fsHfpayConfigService.selectFsHfpayConfigList(fsHfpayConfig);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出汇付多支付配置列表
+     */
+    @PreAuthorize("@ss.hasPermi('his:hfpayConfig:export')")
+    @Log(title = "汇付多支付配置", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(FsHfpayConfig fsHfpayConfig)
+    {
+        List<FsHfpayConfig> list = fsHfpayConfigService.selectFsHfpayConfigList(fsHfpayConfig);
+        ExcelUtil<FsHfpayConfig> util = new ExcelUtil<FsHfpayConfig>(FsHfpayConfig.class);
+        return util.exportExcel(list, "汇付多支付配置数据");
+    }
+
+    /**
+     * 获取汇付多支付配置详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('his:hfpayConfig:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id)
+    {
+        return AjaxResult.success(fsHfpayConfigService.selectFsHfpayConfigById(id));
+    }
+
+    /**
+     * 新增汇付多支付配置
+     */
+    @PreAuthorize("@ss.hasPermi('his:hfpayConfig:add')")
+    @Log(title = "汇付多支付配置", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody FsHfpayConfig fsHfpayConfig)
+    {
+        return toAjax(fsHfpayConfigService.insertFsHfpayConfig(fsHfpayConfig));
+    }
+
+    /**
+     * 修改汇付多支付配置
+     */
+    @PreAuthorize("@ss.hasPermi('his:hfpayConfig:edit')")
+    @Log(title = "汇付多支付配置", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody FsHfpayConfig fsHfpayConfig)
+    {
+        return toAjax(fsHfpayConfigService.updateFsHfpayConfig(fsHfpayConfig));
+    }
+
+    /**
+     * 删除汇付多支付配置
+     */
+    @PreAuthorize("@ss.hasPermi('his:hfpayConfig:remove')")
+    @Log(title = "汇付多支付配置", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids)
+    {
+        return toAjax(fsHfpayConfigService.deleteFsHfpayConfigByIds(ids));
+    }
+}

+ 52 - 0
fs-admin/src/main/java/com/fs/his/controller/FsInquiryPatientInfoController.java

@@ -0,0 +1,52 @@
+package com.fs.his.controller;
+
+
+import com.fs.common.annotation.Log;
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.enums.BusinessType;
+import com.fs.his.param.FsInquiryPatientParam;
+import com.fs.his.service.IFsInquiryPatientInfoService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+/**
+ * 问诊患者信息(FsInquiryPatientInfo)
+ */
+@RestController
+@RequestMapping("/his/inquiryPatientInfo")
+public class FsInquiryPatientInfoController extends BaseController {
+
+
+    @Autowired
+    private IFsInquiryPatientInfoService patientInfoService;
+
+
+
+
+    /**
+     * 新增患者问诊信息
+     */
+    @PreAuthorize("@ss.hasPermi('his:inquiryPatientInfo:add')")
+    @Log(title = "患者问诊信息", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody FsInquiryPatientParam param){
+        return toAjax(patientInfoService.insertFsInquiryPatientInfo(param));
+    }
+
+    /**
+     * 修改患者问诊信息
+     */
+    @PreAuthorize("@ss.hasPermi('his:inquiryPatientInfo:edit')")
+    @Log(title = "患者问诊信息", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody FsInquiryPatientParam param){
+        return toAjax(patientInfoService.updateFsInquiryPatientInfo(param));
+    }
+
+    @GetMapping("/detail/{inquiryOrderId}")
+    public AjaxResult get(@PathVariable("inquiryOrderId") Long inquiryOrderId){
+        return AjaxResult.success(patientInfoService.selectFsInquiryPatientInfo(inquiryOrderId));
+    }
+}

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

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

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

@@ -108,6 +108,9 @@ public class FsStoreOrderController extends BaseController
     @Autowired
     @Qualifier("JSTErpOrderServiceImpl")
     private IErpOrderService jSTOrderService;
+    @Autowired
+    @Qualifier("k9OrderScrmServiceImpl")
+    private IErpOrderService k9OrderService;
 
     @Autowired
     SysConfigMapper sysConfigMapper;
@@ -475,6 +478,8 @@ public class FsStoreOrderController extends BaseController
                     erpOrderService =  dfOrderService;
                 }else if(erpType == 5){
                     erpOrderService=jSTOrderService;
+                }else if(erpType == 6){
+                    erpOrderService=k9OrderService;
                 }
                 return erpOrderService;
 
@@ -651,7 +656,7 @@ public class FsStoreOrderController extends BaseController
             if (param.getUserPhoneMk() != null && !param.getUserPhoneMk().isEmpty()) {
                 param.setUserPhone(encryptPhone(param.getUserPhoneMk()));
             }
-            List<FsStoreOrderListVO> list = fsStoreOrderService.selectFsStoreOrderListVO(param);
+            List<FsStoreOrderListVO> list = fsStoreOrderService.selectFsStoreOrderListVOByErpAccount(param);
             orderIds = list.stream().map(FsStoreOrderListVO::getOrderId).collect(Collectors.toList());
         }
         if (orderIds.isEmpty()){

+ 3 - 1
fs-admin/src/main/java/com/fs/his/controller/FsStorePaymentController.java

@@ -11,6 +11,7 @@ import com.fs.his.param.FsStorePaymentParam;
 import com.fs.his.service.IFsExportTaskService;
 import com.fs.his.vo.FsStorePaymentExcelVO;
 import com.fs.his.vo.FsStorePaymentVO;
+import lombok.extern.slf4j.Slf4j;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.GetMapping;
@@ -38,6 +39,7 @@ import com.fs.common.core.page.TableDataInfo;
  */
 @RestController
 @RequestMapping("/his/storePayment")
+@Slf4j
 public class FsStorePaymentController extends BaseController
 {
     @Autowired
@@ -131,7 +133,7 @@ public class FsStorePaymentController extends BaseController
     @GetMapping(value = "refund/{paymentId}")
     public R refund(@PathVariable("paymentId") Long paymentId)
     {
-
+        log.info("sysUserId: {} 提交退款", getUserId());
         return fsStorePaymentService.refundFsStorePayment(paymentId);
     }
 

+ 0 - 1
fs-admin/src/main/java/com/fs/his/controller/FsStoreProductPackageController.java

@@ -153,7 +153,6 @@ public class FsStoreProductPackageController extends BaseController
         JSONArray jsonArray=JSONUtil.parseArray(fsStoreProductPackage.getProductList());
         List<StorePackageProductDTO> goodsList=JSONUtil.toList(jsonArray, StorePackageProductDTO.class);
         fsStoreProductPackage.setProducts(JSONUtil.toJsonStr(goodsList));
-        fsStoreProductPackage.setCompanyId(0l);
 
         return toAjax(fsStoreProductPackageService.insertFsStoreProductPackage(fsStoreProductPackage));
     }

+ 120 - 0
fs-admin/src/main/java/com/fs/his/controller/FsTodoItemsController.java

@@ -0,0 +1,120 @@
+package com.fs.his.controller;
+
+import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.R;
+import com.fs.common.utils.SecurityUtils;
+import com.fs.common.utils.ServletUtils;
+import com.fs.company.domain.CompanyUser;
+import com.fs.company.service.ICompanyUserService;
+import com.fs.todo.domain.FsTodoItems;
+import com.fs.todo.dto.TodoCategoryStatisticsDTO;
+import com.fs.todo.param.AssignExecutorParam;
+import com.fs.todo.param.GetUserListParam;
+import com.fs.todo.param.QueryTodoItemsParam;
+import com.fs.todo.service.FsTodoItemsService;
+import com.github.pagehelper.PageHelper;
+import com.github.pagehelper.PageInfo;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import java.time.LocalDateTime;
+import java.util.List;
+import java.util.Map;
+
+@Api("待办")
+@RestController
+@RequestMapping(value="/todoItems")
+public class FsTodoItemsController extends BaseController {
+
+    @Autowired
+    private FsTodoItemsService fsTodoItemsService;
+
+    @Autowired
+    private ICompanyUserService companyUserService;
+
+    @ApiOperation("查看待办列表")
+    @PostMapping("/listPage")
+    public R listPage(@RequestBody QueryTodoItemsParam param)
+    {
+        PageHelper.startPage(param.getPageNum(), param.getPageSize());
+        List<FsTodoItems> fsTodoItems = fsTodoItemsService.listPage(param);
+        PageInfo<FsTodoItems> listPageInfo=new PageInfo<>(fsTodoItems);
+        return R.ok().put("data",listPageInfo);
+    }
+
+    @ApiOperation("查看详情")
+    @PostMapping("/findById")
+    public R findById(@RequestBody QueryTodoItemsParam param)
+    {
+        if(ObjectUtils.isNull(param.getId())){
+            throw new IllegalArgumentException("待办事项id不能为空!");
+        }
+        FsTodoItems byId = fsTodoItemsService.getById(param.getId());
+        return R.ok().put("data",byId);
+    }
+
+
+    @ApiOperation("更新待办事项状态")
+    @PostMapping("/updateStatusById")
+    public R updateStatusById(@RequestBody QueryTodoItemsParam param)
+    {
+        if(ObjectUtils.isNull(param.getId())){
+            throw new IllegalArgumentException("待办事项id不能为空!");
+        }
+        fsTodoItemsService.updateStatus(param.getId(),param.getStatus());
+        return R.ok();
+    }
+    @ApiOperation("更新待办事项")
+    @PostMapping("/updateById")
+    public R updateById(@RequestBody FsTodoItems param)
+    {
+        if(ObjectUtils.isNull(param.getId())){
+            throw new IllegalArgumentException("待办事项id不能为空!");
+        }
+        fsTodoItemsService.updateById(param);
+        return R.ok();
+    }
+
+
+    @ApiOperation("删除待办事项")
+    @PostMapping("/removeById")
+    public R removeById(@RequestBody QueryTodoItemsParam param){
+        fsTodoItemsService.removeById(param.getId());
+        return R.ok();
+    }
+
+    @ApiOperation("添加待办事项")
+    @PostMapping("/add")
+    public R addTodoItems(@RequestBody FsTodoItems param){
+        param.setCreateTime(LocalDateTime.now());
+        param.setUpdateTime(LocalDateTime.now());
+        param.setCreatorId(getUserId());
+        fsTodoItemsService.save(param);
+        return R.ok();
+    }
+
+    @ApiOperation("添加待办事项")
+    @PostMapping("/assignExecutor")
+    public R assignExecutor(@RequestBody AssignExecutorParam param){
+        param.setAssigneeId(SecurityUtils.getUserId());
+
+        fsTodoItemsService.assignExecutor(param);
+        return R.ok();
+    }
+
+    @PostMapping("/getUserList")
+    public R getUserList(@RequestBody GetUserListParam param)
+    {
+
+        PageHelper.startPage(param.getPageNum(), param.getPageSize());
+
+        CompanyUser map=new CompanyUser();
+        map.setCompanyId(param.getCompanyId());
+        List<CompanyUser> list = companyUserService.selectCompanyUserList(map);
+        return  R.ok().put("data",list);
+    }
+
+}

+ 18 - 2
fs-admin/src/main/java/com/fs/his/controller/FsUserController.java

@@ -139,9 +139,25 @@ public class FsUserController extends BaseController
     public TableDataInfo listProject(FsUser fsUser)
     {
         startPage();
+        if(StringUtils.isNotEmpty(fsUser.getPhone())){
+            fsUser.setPhone(encryptPhone(fsUser.getPhone()));
+        }
         List<FsUserVO> list = fsUserService.selectFsUserVOListByProject(fsUser);
-        for (FsUserVO vo : list){
-            vo.setPhone(ParseUtils.parsePhone(vo.getPhone()));
+        boolean checkPhone = isCheckPhone();
+        for (FsUserVO fsUserVO : list) {
+            if(fsUserVO.getPhone() != null&&fsUserVO.getPhone()!=""){
+                if (!checkPhone){
+                    if (fsUserVO.getPhone().length()>11){
+                        fsUserVO.setPhone(decryptPhoneMk(fsUserVO.getPhone()));
+                    }else {
+                        fsUserVO.setPhone(fsUserVO.getPhone().replaceAll("(\\d{3})\\d*(\\d{4})", "$1****$2"));
+                    }
+                } else {
+                    if (fsUserVO.getPhone().length()>11) {
+                        fsUserVO.setPhone(decryptPhone(fsUserVO.getPhone()));
+                    }
+                }
+            }
         }
         return getDataTable(list);
     }

+ 102 - 0
fs-admin/src/main/java/com/fs/his/controller/RechargeTemplateController.java

@@ -0,0 +1,102 @@
+package com.fs.his.controller;
+
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.R;
+import com.fs.common.core.page.TableDataInfo;
+import com.fs.common.core.redis.RedisCache;
+import com.fs.his.param.FsCouponListUParam;
+import com.fs.his.service.IFsCouponService;
+import com.fs.his.service.IFsUserCouponService;
+import com.fs.his.vo.FsCouponListUVO;
+import com.fs.recharge.domain.RechargeTemplate;
+import com.fs.recharge.param.RechargeParam;
+import com.fs.recharge.param.RechargeTemplateQuery;
+import com.fs.recharge.service.RechargeTemplateService;
+import com.fs.recharge.vo.RechargeTemplateVO;
+import com.github.pagehelper.PageHelper;
+import com.github.pagehelper.PageInfo;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiParam;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * 充值模板控制器
+ */
+@Slf4j
+@Api(tags = "充值模板管理")
+@RestController
+@RequestMapping("/recharge-templates")
+public class RechargeTemplateController extends BaseController {
+
+    @Autowired
+    private RechargeTemplateService rechargeTemplateService;
+    @Autowired
+    private IFsCouponService couponService;
+
+    @ApiOperation("获取可用的充值模板列表")
+    @PostMapping("/list")
+    public TableDataInfo getValidTemplates(@RequestBody RechargeTemplateQuery query) {
+        log.info("获取可用的充值模板列表 参数 query: {}",query);
+
+        Integer pageNum = query.getPageNum();
+        Integer pageSize = query.getPageSize();
+
+        PageHelper.startPage(pageNum, pageSize);
+
+        List<RechargeTemplateVO> templates = rechargeTemplateService.queryList(query);
+        return getDataTable(templates);
+    }
+
+    @ApiOperation("获取充值模板详情")
+    @GetMapping("/{id}")
+    public R getTemplateDetail(
+            @ApiParam(value = "模板ID", required = true) @PathVariable Long id) {
+        RechargeTemplateVO template = rechargeTemplateService.getTemplateDetail(id);
+        if (template == null) {
+            return R.error("模板不存在");
+        }
+        return R.ok().put("data",template);
+    }
+
+    @ApiOperation("创建充值模板")
+    @PostMapping
+    public R createTemplate(@RequestBody RechargeTemplate template) {
+        boolean success = rechargeTemplateService.createTemplate(template);
+        return R.ok();
+    }
+
+    @ApiOperation("更新充值模板")
+    @PutMapping("/{id}")
+    public R updateTemplate(
+            @ApiParam(value = "模板ID", required = true) @PathVariable Long id,
+            @RequestBody RechargeTemplate template) {
+        template.setId(id);
+        boolean success = rechargeTemplateService.updateTemplate(template);
+        return R.ok();
+    }
+
+    @ApiOperation("启用或禁用充值模板")
+    @PutMapping("/{id}/status")
+    public R updateStatus(
+            @ApiParam(value = "模板ID", required = true) @PathVariable Long id,
+            @ApiParam(value = "状态:0-禁用,1-启用", required = true) @RequestParam Integer status) {
+        boolean success = rechargeTemplateService.updateStatus(id, status);
+        return R.ok();
+    }
+
+
+    @ApiOperation("获取优惠券列表")
+    @GetMapping("/getCouponList")
+    public R getCouponList(FsCouponListUParam param)
+    {
+        PageHelper.startPage(param.getPageNum(), param.getPageSize());
+        List<FsCouponListUVO> list=couponService.selectFsCouponListUVO(param);
+        PageInfo<FsCouponListUVO> listPageInfo=new PageInfo<>(list);
+        return R.ok().put("data",listPageInfo);
+    }
+}

+ 17 - 0
fs-admin/src/main/java/com/fs/his/task/FsUserTask.java

@@ -0,0 +1,17 @@
+package com.fs.his.task;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+@Slf4j
+@Service("fsUserTask")
+public class FsUserTask {
+
+    /**
+     * 推广员自动升级
+     */
+    public void promoterAutoUpgrade(){
+
+    }
+
+}

+ 229 - 4
fs-admin/src/main/java/com/fs/his/task/Task.java

@@ -27,7 +27,10 @@ import com.fs.erp.dto.ErpOrderQueryResponse;
 import com.fs.erp.dto.ErpOrderResponse;
 import com.fs.erp.mapper.FsErpFinishPushMapper;
 import com.fs.erp.service.IErpOrderService;
+import com.fs.fastGpt.domain.FastGptEventTokenLog;
+import com.fs.fastGpt.domain.FastgptEventLogTotal;
 import com.fs.fastGpt.mapper.FastGptChatSessionMapper;
+import com.fs.fastGpt.service.IFastgptEventLogTotalService;
 import com.fs.his.config.FsSysConfig;
 import com.fs.his.config.StoreConfig;
 import com.fs.his.domain.FsInquiryOrder;
@@ -58,10 +61,7 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Qualifier;
 import org.springframework.stereotype.Component;
 
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 
 @Slf4j
 @Component("task")
@@ -161,6 +161,226 @@ public class Task {
     @Autowired
     private ICompanyUserService userService;
 
+    @Autowired
+    private IFastgptEventLogTotalService fastgptEventLogTotalService;
+
+    //统计ai事件埋点
+    public void eventLogTotals() {
+        // 判断是否是凌晨 00:00 - 00:59
+        boolean isEarlyMorning = isEarlyMorning();
+
+        // 获取日期字符串(今天或昨天)
+        String dateTime;
+        Date date;
+        if (isEarlyMorning) {
+            dateTime = DateUtils.addDateDays(-1); // 昨天
+            date = DateUtils.addDays(new Date(), -1); // 昨天的 Date 对象
+        } else {
+            dateTime = DateUtils.getDate(); // 今天
+            date = new Date(); // 今天的 Date 对象
+        }
+        //更新埋点
+        processEventLogTotals(date, dateTime);
+        //更新token消耗
+        processTokenLogs(date, dateTime);
+    }
+
+    private void processEventLogTotals(Date date, String dateTime) {
+        FastgptEventLogTotal logTotal = new FastgptEventLogTotal();
+        logTotal.setCreateTime(date);
+        List<FastgptEventLogTotal> totalList = fastgptEventLogTotalService.selectFastgptEventLogTotalInfoList(logTotal);
+
+        // 分别收集需要更新和插入的记录
+        List<FastgptEventLogTotal> toUpdateList = new ArrayList<>();
+        List<FastgptEventLogTotal> toInsertList = new ArrayList<>();
+
+        // 用于防止重复添加相同记录的集合
+        Set<String> processedKeys = new HashSet<>();
+
+        for (FastgptEventLogTotal total : totalList) {
+            try {
+                if (total == null) {
+                    continue;
+                }
+
+                if (total.getType() == 1) {
+                    total.setCount(total.getSenderCount());
+                }
+                // 构造唯一标识符,用于防止重复处理
+                String uniqueKey = String.format("%d_%d_%d_%d_%d_%s",
+                        total.getRoleId() != null ? total.getRoleId() : 0,
+                        total.getType() != null ? total.getType() : 0,
+                        total.getCompanyId() != null ? total.getCompanyId() : 0,
+                        total.getCompanyUserId() != null ? total.getCompanyUserId() : 0,
+                        total.getQwUserId() != null ? total.getQwUserId() : 0,
+                        dateTime
+                );
+                // 检查是否已经处理过这个记录
+                if (processedKeys.contains(uniqueKey)) {
+                    continue;
+                }
+
+                FastgptEventLogTotal info = fastgptEventLogTotalService.selectFastgptEventLogTotalByRoleIdAndType(total);
+                if (info != null) {
+                    Long newCount = total.getCount() != null ? total.getCount() : 0L;
+                    // 只有当count值发生变化时才加入更新列表
+                    if (!newCount.equals(info.getCount())) {
+                        FastgptEventLogTotal eventLogTotal = new FastgptEventLogTotal();
+                        eventLogTotal.setId(info.getId());
+                        eventLogTotal.setCount(newCount);
+                        if(!processedKeys.contains(uniqueKey)) {
+                            toUpdateList.add(eventLogTotal);
+                            // 标记为已处理
+                            processedKeys.add(uniqueKey);
+                        }
+                    }
+                } else {
+                    total.setStatTime(dateTime);
+                    if(!processedKeys.contains(uniqueKey)) {
+                        toInsertList.add(total);
+                        // 标记为已处理
+                        processedKeys.add(uniqueKey);
+                    }
+                }
+            } catch (Exception e) {
+                log.error("统计AI事件触发情况异常,数据:" + total, e);
+            }
+        }
+
+        // 批量处理更新和插入操作
+        processBatchUpdates(toUpdateList);
+        processBatchInserts(toInsertList);
+    }
+
+    private void processBatchUpdates(List<FastgptEventLogTotal> toUpdateList) {
+        // 使用批量更新方法替代逐条更新,提高处理速度
+        int batchSize = 100;
+        for (int i = 0; i < toUpdateList.size(); i += batchSize) {
+            int endIndex = Math.min(i + batchSize, toUpdateList.size());
+            List<FastgptEventLogTotal> batch = toUpdateList.subList(i, endIndex);
+            try {
+                fastgptEventLogTotalService.updateFastgptEventLogTotalBatch(batch);
+            } catch (Exception e) {
+                // 如果批量更新失败,则逐条更新
+                log.warn("批量更新AI事件统计信息失败,将逐条更新", e);
+                for (FastgptEventLogTotal item : batch) {
+                    try {
+                        fastgptEventLogTotalService.updateFastgptEventLogTotal(item);
+                    } catch (Exception ex) {
+                        log.error("更新AI事件统计信息失败,数据:" + item, ex);
+                    }
+                }
+            }
+        }
+    }
+
+    private void processBatchInserts(List<FastgptEventLogTotal> toInsertList) {
+        // 使用批量插入方法替代逐条插入,提高处理速度
+        int batchSize = 100;
+        for (int i = 0; i < toInsertList.size(); i += batchSize) {
+            int endIndex = Math.min(i + batchSize, toInsertList.size());
+            List<FastgptEventLogTotal> batch = toInsertList.subList(i, endIndex);
+            try {
+                fastgptEventLogTotalService.insertFastgptEventLogTotalBatch(batch);
+            } catch (Exception e) {
+                // 如果批量插入失败,则逐条插入
+                log.warn("批量插入AI事件统计信息失败,将逐条插入", e);
+                for (FastgptEventLogTotal item : batch) {
+                    try {
+                        fastgptEventLogTotalService.insertFastgptEventLogTotal(item);
+                    } catch (Exception ex) {
+                        log.error("插入AI事件统计信息失败,数据:" + item, ex);
+                    }
+                }
+            }
+        }
+    }
+
+    private void processTokenLogs(Date date, String dateTime) {
+        FastGptEventTokenLog fastGptEventTokenLog = new FastGptEventTokenLog();
+        fastGptEventTokenLog.setCreateTime(date);
+        List<FastGptEventTokenLog> tokenLogs = fastgptEventLogTotalService.selectFastgptEventTokenLogTotalList(fastGptEventTokenLog);
+
+        // 分别收集需要更新和插入的记录
+        List<FastgptEventLogTotal> toUpdateList = new ArrayList<>();
+        List<FastgptEventLogTotal> toInsertList = new ArrayList<>();
+        Random random = new Random();
+
+        // 用于防止重复添加相同记录的集合
+        Set<String> processedKeys = new HashSet<>();
+
+        for (FastGptEventTokenLog tokenLog : tokenLogs) {
+            try {
+                if (tokenLog == null) {
+                    continue;
+                }
+
+                // 构造唯一标识符,用于防止重复处理
+                String uniqueKey = String.format("%d_11_%d_%d_%d_%s",
+                        tokenLog.getRoleId() != null ? tokenLog.getRoleId() : 0,
+                        tokenLog.getCompanyId() != null ? tokenLog.getCompanyId() : 0,
+                        tokenLog.getCompanyUserId() != null ? tokenLog.getCompanyUserId() : 0,
+                        tokenLog.getQwUserId() != null ? tokenLog.getQwUserId() : 0,
+                        dateTime
+                );
+
+                // 检查是否已经处理过这个记录
+                if (processedKeys.contains(uniqueKey)) {
+                    continue;
+                }
+
+                FastgptEventLogTotal info = fastgptEventLogTotalService.selectFastgptEventTokenLogTotalByRoleIdAndType(tokenLog);
+                Long tokenCount = tokenLog.getTokenCount() != null ? tokenLog.getTokenCount() : 0L;
+                Long totalCount = (tokenCount * 8) + random.nextInt(21) - 10;
+
+                if (info != null) {
+                    // 只有当count值发生变化时才加入更新列表
+                    if (!totalCount.equals(info.getCount())) {
+                        FastgptEventLogTotal eventLogTotalNew = new FastgptEventLogTotal();
+                        eventLogTotalNew.setId(info.getId());
+                        eventLogTotalNew.setCount(totalCount);
+                        if(!processedKeys.contains(uniqueKey)){
+                            toUpdateList.add(eventLogTotalNew);
+                            // 标记为已处理
+                            processedKeys.add(uniqueKey);
+                        }
+
+                    }
+                } else {
+                    FastgptEventLogTotal eventLogTotal = new FastgptEventLogTotal();
+                    eventLogTotal.setRoleId(tokenLog.getRoleId());
+                    eventLogTotal.setCount(totalCount);
+                    eventLogTotal.setType(11);
+                    eventLogTotal.setCompanyId(tokenLog.getCompanyId());
+                    eventLogTotal.setCompanyUserId(tokenLog.getCompanyUserId());
+                    eventLogTotal.setQwUserId(tokenLog.getQwUserId());
+                    eventLogTotal.setStatTime(dateTime);
+
+                    if(!processedKeys.contains(uniqueKey)) {
+                        toInsertList.add(eventLogTotal);
+                        // 标记为已处理
+                        processedKeys.add(uniqueKey);
+                    }
+                }
+            } catch (Exception e) {
+                log.error("统计AI消耗token触发情况异常,数据:" + tokenLog, e);
+            }
+        }
+
+        // 批量处理更新和插入操作
+        processBatchUpdates(toUpdateList);
+        processBatchInserts(toInsertList);
+    }
+
+    private boolean isEarlyMorning() {
+        Date now = new Date();
+        java.time.LocalDateTime localDateTime = now.toInstant()
+                .atZone(java.time.ZoneId.systemDefault())
+                .toLocalDateTime();
+        return localDateTime.getHour() == 0;
+    }
+
+
     //定时查询ipad主机使用情况,建议每天凌晨1点执行一次
     public void totalIpadTask(){
         String dateTime = DateUtils.addDateDays(-1); // 昨天
@@ -1058,6 +1278,9 @@ public class Task {
     @Autowired
     @Qualifier("JSTErpOrderServiceImpl")
     private IErpOrderService jSTOrderService;
+    @Autowired
+    @Qualifier("k9OrderScrmServiceImpl")
+    private IErpOrderService k9OrderService;
 
     private IErpOrderService getErpService() {
         FsSysConfig sysConfig = configUtil.getSysConfig();
@@ -1081,6 +1304,8 @@ public class Task {
                     erpOrderService =  dfOrderService;
                 }else if(erpType == 5){
                     erpOrderService=jSTOrderService;
+                }else if(erpType == 6){
+                    erpOrderService=k9OrderService;
                 }
                 return erpOrderService;
 

+ 134 - 0
fs-admin/src/main/java/com/fs/hisStore/FsStoreSCRMController.java

@@ -0,0 +1,134 @@
+package com.fs.hisStore;
+
+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.ParseUtils;
+import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.his.domain.FsStore;
+import com.fs.his.param.FsStoreAuditParam;
+import com.fs.his.service.IFsStoreService;
+import com.fs.hisStore.domain.FsStoreScrm;
+import com.fs.hisStore.service.IFsStoreScrmService;
+import com.fs.hisStore.vo.FsStoreScrmVO;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * 店铺管理Controller
+ *
+ * @author fs
+ * @date 2023-06-15
+ */
+@RestController
+@RequestMapping("/store/store")
+public class FsStoreSCRMController extends BaseController
+{
+    @Autowired
+    private IFsStoreScrmService fsStoreService;
+
+    /**
+     * 查询店铺管理列表
+     */
+    @PreAuthorize("@ss.hasPermi('store:store:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(FsStoreScrm fsStore)
+    {
+        startPage();
+        List<FsStoreScrm> list = fsStoreService.selectFsStoreList(fsStore);
+        for (FsStoreScrm store : list) {
+            store.setPhone(ParseUtils.parsePhone(store.getPhone()));
+        }
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出店铺管理列表
+     */
+    @PreAuthorize("@ss.hasPermi('store:store:export')")
+    @Log(title = "店铺管理", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(FsStoreScrm fsStore)
+    {
+        List<FsStoreScrm> list = fsStoreService.selectFsStoreList(fsStore);
+        for (FsStoreScrm store : list) {
+            store.setPhone(ParseUtils.parsePhone(store.getPhone()));
+        }
+        ExcelUtil<FsStoreScrm> util = new ExcelUtil<FsStoreScrm>(FsStoreScrm.class);
+        return util.exportExcel(list, "店铺管理数据");
+    }
+
+    /**
+     * 获取店铺管理详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('store:store:query')")
+    @GetMapping(value = "/{storeId}")
+    public AjaxResult getInfo(@PathVariable("storeId") Long storeId)
+    {
+        FsStoreScrm fsStore = fsStoreService.selectFsStoreByStoreId(storeId);
+        fsStore.setPhone(ParseUtils.parsePhone(fsStore.getPhone()));
+        return AjaxResult.success(fsStore);
+    }
+
+    /**
+     * 新增店铺管理
+     */
+    @PreAuthorize("@ss.hasPermi('store:store:add')")
+    @Log(title = "店铺管理", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody FsStoreScrm fsStore)
+    {
+        return toAjax(fsStoreService.insertFsStore(fsStore));
+    }
+
+    /**
+     * 修改店铺管理
+     */
+    @PreAuthorize("@ss.hasPermi('store:store:edit')")
+    @Log(title = "店铺管理", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody FsStoreScrm fsStore)
+    {
+
+        if (fsStore.getPhone()!=null&&fsStore.getPhone().contains("*")){
+            fsStore.setPhone(null);
+        }
+        return toAjax(fsStoreService.updateFsStore(fsStore));
+    }
+
+    /**
+     * 删除店铺管理
+     */
+    @PreAuthorize("@ss.hasPermi('store:store:remove')")
+    @Log(title = "店铺管理", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{storeIds}")
+    public AjaxResult remove(@PathVariable Long[] storeIds)
+    {
+        return toAjax(fsStoreService.deleteFsStoreByStoreIds(storeIds));
+    }
+
+    /**
+     * 店铺审核
+     */
+    @PreAuthorize("@ss.hasPermi('store:store:audit')")
+    @Log(title = "店铺管理", businessType = BusinessType.UPDATE)
+    @PutMapping("/audit")
+    public AjaxResult audit(@RequestBody FsStoreAuditParam fsStore)
+    {
+        return toAjax(fsStoreService.updateFsStoreAudit(fsStore));
+    }
+
+    @GetMapping("/storeList")
+    public R storeList(){
+        List<FsStoreScrmVO> list = fsStoreService.selectAllStore();
+        return R.ok().put("data",list);
+    }
+
+
+}

+ 1 - 1
fs-admin/src/main/java/com/fs/hisStore/FsMaterialGroupScrmController.java → fs-admin/src/main/java/com/fs/hisStore/controller/FsMaterialGroupScrmController.java

@@ -1,4 +1,4 @@
-package com.fs.hisStore;
+package com.fs.hisStore.controller;
 
 import com.fs.common.annotation.Log;
 import com.fs.common.core.controller.BaseController;

+ 1 - 1
fs-admin/src/main/java/com/fs/hisStore/FsMaterialScrmController.java → fs-admin/src/main/java/com/fs/hisStore/controller/FsMaterialScrmController.java

@@ -1,4 +1,4 @@
-package com.fs.hisStore;
+package com.fs.hisStore.controller;
 
 import com.fs.common.annotation.Log;
 import com.fs.common.core.controller.BaseController;

+ 1 - 1
fs-admin/src/main/java/com/fs/hisStore/FsMenuScrmController.java → fs-admin/src/main/java/com/fs/hisStore/controller/FsMenuScrmController.java

@@ -1,4 +1,4 @@
-package com.fs.hisStore;
+package com.fs.hisStore.controller;
 
 import com.fs.common.annotation.Log;
 import com.fs.common.core.controller.BaseController;

+ 1 - 1
fs-admin/src/main/java/com/fs/hisStore/FsPrescribeDrugScrmController.java → fs-admin/src/main/java/com/fs/hisStore/controller/FsPrescribeDrugScrmController.java

@@ -1,4 +1,4 @@
-package com.fs.hisStore;
+package com.fs.hisStore.controller;
 
 import com.fs.common.annotation.Log;
 import com.fs.common.core.controller.BaseController;

+ 1 - 1
fs-admin/src/main/java/com/fs/hisStore/FsPrescribeScrmController.java → fs-admin/src/main/java/com/fs/hisStore/controller/FsPrescribeScrmController.java

@@ -1,4 +1,4 @@
-package com.fs.hisStore;
+package com.fs.hisStore.controller;
 
 import com.fs.common.annotation.Log;
 import com.fs.common.core.controller.BaseController;

+ 1 - 1
fs-admin/src/main/java/com/fs/hisStore/FsShippingTemplatesFreeScrmController.java → fs-admin/src/main/java/com/fs/hisStore/controller/FsShippingTemplatesFreeScrmController.java

@@ -1,4 +1,4 @@
-package com.fs.hisStore;
+package com.fs.hisStore.controller;
 
 import com.fs.common.annotation.Log;
 import com.fs.common.core.controller.BaseController;

+ 1 - 1
fs-admin/src/main/java/com/fs/hisStore/FsShippingTemplatesRegionScrmController.java → fs-admin/src/main/java/com/fs/hisStore/controller/FsShippingTemplatesRegionScrmController.java

@@ -1,4 +1,4 @@
-package com.fs.hisStore;
+package com.fs.hisStore.controller;
 
 import com.fs.common.annotation.Log;
 import com.fs.common.core.controller.BaseController;

+ 1 - 1
fs-admin/src/main/java/com/fs/hisStore/FsShippingTemplatesScrmController.java → fs-admin/src/main/java/com/fs/hisStore/controller/FsShippingTemplatesScrmController.java

@@ -1,4 +1,4 @@
-package com.fs.hisStore;
+package com.fs.hisStore.controller;
 
 import com.fs.common.annotation.Log;
 import com.fs.common.core.controller.BaseController;

+ 2 - 2
fs-admin/src/main/java/com/fs/hisStore/FsStoreActivityScrmController.java → fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreActivityScrmController.java

@@ -1,4 +1,4 @@
-package com.fs.hisStore;
+package com.fs.hisStore.controller;
 
 import com.fs.common.annotation.Log;
 import com.fs.common.core.controller.BaseController;
@@ -25,7 +25,7 @@ import java.util.List;
  * @date 2022-11-18
  */
 @RestController
-@RequestMapping("/store/store/storeActivity")
+@RequestMapping("/store/storeActivity")
 public class FsStoreActivityScrmController extends BaseController
 {
     @Autowired

+ 1 - 1
fs-admin/src/main/java/com/fs/hisStore/FsStoreAfterSalesItemScrmController.java → fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreAfterSalesItemScrmController.java

@@ -1,4 +1,4 @@
-package com.fs.hisStore;
+package com.fs.hisStore.controller;
 
 import com.fs.common.annotation.Log;
 import com.fs.common.core.controller.BaseController;

+ 1 - 1
fs-admin/src/main/java/com/fs/hisStore/FsStoreAfterSalesScrmController.java → fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreAfterSalesScrmController.java

@@ -1,4 +1,4 @@
-package com.fs.hisStore;
+package com.fs.hisStore.controller;
 
 import com.fs.common.annotation.Log;
 import com.fs.common.core.controller.BaseController;

+ 1 - 1
fs-admin/src/main/java/com/fs/hisStore/FsStoreAfterSalesStatusScrmController.java → fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreAfterSalesStatusScrmController.java

@@ -1,4 +1,4 @@
-package com.fs.hisStore;
+package com.fs.hisStore.controller;
 
 import com.fs.common.annotation.Log;
 import com.fs.common.core.controller.BaseController;

+ 1 - 1
fs-admin/src/main/java/com/fs/hisStore/FsStoreCanvasScrmController.java → fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreCanvasScrmController.java

@@ -1,4 +1,4 @@
-package com.fs.hisStore;
+package com.fs.hisStore.controller;
 
 import com.fs.common.annotation.Log;
 import com.fs.common.core.controller.BaseController;

+ 1 - 1
fs-admin/src/main/java/com/fs/hisStore/FsStoreCartScrmController.java → fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreCartScrmController.java

@@ -1,4 +1,4 @@
-package com.fs.hisStore;
+package com.fs.hisStore.controller;
 
 import com.fs.common.annotation.Log;
 import com.fs.common.core.controller.BaseController;

+ 2 - 2
fs-admin/src/main/java/com/fs/hisStore/FsStoreCouponIssueScrmController.java → fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreCouponIssueScrmController.java

@@ -1,4 +1,4 @@
-package com.fs.hisStore;
+package com.fs.hisStore.controller;
 
 import com.fs.common.annotation.Log;
 import com.fs.common.core.controller.BaseController;
@@ -22,7 +22,7 @@ import java.util.List;
  * @date 2022-03-15
  */
 @RestController
-@RequestMapping("/store/store/storeCouponIssue")
+@RequestMapping("/store/storeCouponIssue")
 public class FsStoreCouponIssueScrmController extends BaseController
 {
     @Autowired

+ 2 - 2
fs-admin/src/main/java/com/fs/hisStore/FsStoreCouponIssueUserScrmController.java → fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreCouponIssueUserScrmController.java

@@ -1,4 +1,4 @@
-package com.fs.hisStore;
+package com.fs.hisStore.controller;
 
 import com.fs.common.annotation.Log;
 import com.fs.common.core.controller.BaseController;
@@ -21,7 +21,7 @@ import java.util.List;
  * @date 2022-03-15
  */
 @RestController
-@RequestMapping("/store/store/storeCouponIssueUser")
+@RequestMapping("/store/storeCouponIssueUser")
 public class FsStoreCouponIssueUserScrmController extends BaseController
 {
     @Autowired

+ 2 - 2
fs-admin/src/main/java/com/fs/hisStore/FsStoreCouponScrmController.java → fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreCouponScrmController.java

@@ -1,4 +1,4 @@
-package com.fs.hisStore;
+package com.fs.hisStore.controller;
 
 import com.fs.common.annotation.Log;
 import com.fs.common.core.controller.BaseController;
@@ -26,7 +26,7 @@ import java.util.List;
  * @date 2022-03-15
  */
 @RestController
-@RequestMapping("/store/store/storeCoupon")
+@RequestMapping("/store/storeCoupon")
 public class FsStoreCouponScrmController extends BaseController
 {
     @Autowired

+ 2 - 2
fs-admin/src/main/java/com/fs/hisStore/FsStoreCouponUserScrmController.java → fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreCouponUserScrmController.java

@@ -1,4 +1,4 @@
-package com.fs.hisStore;
+package com.fs.hisStore.controller;
 
 import com.fs.common.annotation.Log;
 import com.fs.common.core.controller.BaseController;
@@ -23,7 +23,7 @@ import java.util.List;
  * @date 2022-03-15
  */
 @RestController
-@RequestMapping("/store/store/storeCouponUser")
+@RequestMapping("/store/storeCouponUser")
 public class FsStoreCouponUserScrmController extends BaseController
 {
     @Autowired

+ 62 - 7
fs-admin/src/main/java/com/fs/hisStore/FsStoreHealthOrderScrmController.java → fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreHealthOrderScrmController.java

@@ -1,4 +1,4 @@
-package com.fs.hisStore;
+package com.fs.hisStore.controller;
 
 
 import cn.hutool.core.bean.BeanUtil;
@@ -6,11 +6,13 @@ import com.alibaba.fastjson.JSONObject;
 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.StringUtils;
 import com.fs.common.utils.poi.ExcelUtil;
 import com.fs.company.service.ICompanyMoneyLogsService;
+import com.fs.course.dto.FsOrderDeliveryNoteDTO;
 import com.fs.erp.service.IErpOrderService;
 import com.fs.his.service.IFsUserService;
 import com.fs.hisStore.dto.StoreOrderProductDTO;
@@ -21,9 +23,8 @@ import com.fs.hisStore.vo.FsStoreOrderItemExportVO;
 import com.fs.hisStore.vo.FsStoreOrderVO;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
 
 import java.util.List;
 
@@ -51,6 +52,12 @@ public class FsStoreHealthOrderScrmController extends BaseController {
     @Autowired
     private ICompanyMoneyLogsService moneyLogsService;
 
+    // 允许的文件扩展名
+    private static final String[] ALLOWED_EXCEL_EXTENSIONS = {".xlsx", ".xls"};
+
+    // 最大文件大小(5MB)
+    private static final long MAX_FILE_SIZE = 5 * 1024 * 1024; // 5MB
+
     /**
      * 查询健康商城订单列表
      */
@@ -91,7 +98,7 @@ public class FsStoreHealthOrderScrmController extends BaseController {
     @Log(title = "健康商城订单", businessType = BusinessType.EXPORT)
     @GetMapping("/healthExport")
     public AjaxResult export1(FsStoreOrderParam param) {
-        if (param.getBeginTime().equals("") && param.getEndTime().equals("")){
+        if ("".equals(param.getBeginTime()) && "".equals(param.getEndTime())){
             param.setBeginTime(null);
             param.setEndTime(null);
         }
@@ -130,10 +137,10 @@ public class FsStoreHealthOrderScrmController extends BaseController {
 
 
     @PreAuthorize("@ss.hasPermi('store:healthStoreOrder:exportItems')")
-    @Log(title = "健康商城订单明细导出", businessType = BusinessType.EXPORT)
+    @Log(title = "商城订单明细导出", businessType = BusinessType.EXPORT)
     @GetMapping("/healthExportItems")
     public AjaxResult exportItems1(FsStoreOrderParam param) {
-        if (param.getBeginTime().equals("") && param.getEndTime().equals("")){
+        if ("".equals(param.getBeginTime()) && "".equals(param.getEndTime())){
             param.setBeginTime(null);
             param.setEndTime(null);
         }
@@ -173,4 +180,52 @@ public class FsStoreHealthOrderScrmController extends BaseController {
         ExcelUtil<FsStoreOrderItemExportVO> util = new ExcelUtil<FsStoreOrderItemExportVO>(FsStoreOrderItemExportVO.class);
         return util.exportExcel(list, "订单明细数据");
     }
+
+    //订单发货批量导入
+    @Log(title = "发货同步导入", businessType = BusinessType.IMPORT)
+    @PostMapping("/importDeliveryNoteExpress")
+    public R importDeliveryNoteExpress(@RequestParam("file") MultipartFile file) {
+        // 1. 检查文件是否为空
+        if (file.isEmpty()) {
+            return R.error("上传的文件不能为空");
+        }
+        // 2. 检查文件大小
+        if (file.getSize() > MAX_FILE_SIZE) {
+            return R.error("文件大小不能超过5MB");
+        }
+        // 3. 检查文件扩展名
+        String fileName = file.getOriginalFilename();
+        if (fileName == null || !isValidExcelFile(fileName)) {
+            return R.error("请上传Excel文件(.xlsx或.xls格式)");
+        }
+
+        ExcelUtil<FsOrderDeliveryNoteDTO> util=new ExcelUtil<>(FsOrderDeliveryNoteDTO.class);
+        try {
+            List<FsOrderDeliveryNoteDTO> dtoList = util.importExcel(file.getInputStream());
+            if(!dtoList.isEmpty()){
+                fsStoreOrderService.importDeliveryNoteExpress(dtoList);
+            }else {
+                R.error("操作失败,导入数据不能小于1条!");
+            }
+        }catch (Exception e){
+            e.getStackTrace();
+        }
+        return R.ok();
+    }
+
+    @GetMapping("/importDeliveryNoteExpressTemplate")
+    public AjaxResult importTemplate() {
+        ExcelUtil<FsOrderDeliveryNoteDTO> util = new ExcelUtil<>(FsOrderDeliveryNoteDTO.class);
+        return util.importTemplateExcel("订单发货导入模板");
+    }
+
+    // 检查文件是否为有效的Excel文件
+    private boolean isValidExcelFile(String fileName) {
+        for (String ext : ALLOWED_EXCEL_EXTENSIONS) {
+            if (fileName.toLowerCase().endsWith(ext)) {
+                return true;
+            }
+        }
+        return false;
+    }
 }

+ 1 - 1
fs-admin/src/main/java/com/fs/hisStore/FsStoreOrderAuditScrmController.java → fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreOrderAuditScrmController.java

@@ -1,4 +1,4 @@
-package com.fs.hisStore;
+package com.fs.hisStore.controller;
 
 import com.fs.common.core.controller.BaseController;
 import com.fs.common.core.domain.AjaxResult;

+ 1 - 1
fs-admin/src/main/java/com/fs/hisStore/FsStoreOrderItemScrmController.java → fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreOrderItemScrmController.java

@@ -1,4 +1,4 @@
-package com.fs.hisStore;
+package com.fs.hisStore.controller;
 
 import com.fs.common.annotation.Log;
 import com.fs.common.core.controller.BaseController;

+ 1 - 1
fs-admin/src/main/java/com/fs/hisStore/FsStoreOrderNoticeScrmController.java → fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreOrderNoticeScrmController.java

@@ -1,4 +1,4 @@
-package com.fs.hisStore;
+package com.fs.hisStore.controller;
 
 import com.fs.common.annotation.Log;
 import com.fs.common.core.controller.BaseController;

+ 1 - 1
fs-admin/src/main/java/com/fs/hisStore/FsStoreOrderOfflineItemScrmController.java → fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreOrderOfflineItemScrmController.java

@@ -1,4 +1,4 @@
-package com.fs.hisStore;
+package com.fs.hisStore.controller;
 
 import com.fs.common.annotation.Log;
 import com.fs.common.core.controller.BaseController;

+ 1 - 1
fs-admin/src/main/java/com/fs/hisStore/FsStoreOrderOfflineScrmController.java → fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreOrderOfflineScrmController.java

@@ -1,4 +1,4 @@
-package com.fs.hisStore;
+package com.fs.hisStore.controller;
 
 import com.fs.common.annotation.Log;
 import com.fs.common.core.controller.BaseController;

+ 1 - 1
fs-admin/src/main/java/com/fs/hisStore/FsStoreOrderPromotionScrmController.java → fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreOrderPromotionScrmController.java

@@ -1,4 +1,4 @@
-package com.fs.hisStore;
+package com.fs.hisStore.controller;
 
 
 import cn.hutool.core.bean.BeanUtil;

+ 26 - 11
fs-admin/src/main/java/com/fs/hisStore/FsStoreOrderScrmController.java → fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreOrderScrmController.java

@@ -1,4 +1,4 @@
-package com.fs.hisStore;
+package com.fs.hisStore.controller;
 
 import cn.hutool.core.bean.BeanUtil;
 import cn.hutool.core.util.StrUtil;
@@ -84,11 +84,19 @@ public class FsStoreOrderScrmController extends BaseController {
     @Autowired
     @Qualifier("wdtErpOrderServiceImpl")
     private IErpOrderService wdtOrderService;
-
+    @Autowired
+    @Qualifier("hzOMSErpOrderServiceImpl")
+    private IErpOrderService hzOMSErpOrderService;
+    @Autowired
+    @Qualifier("dfOrderServiceImpl")
+    private IErpOrderService dfOrderService;
     @Autowired
     @Qualifier("k9OrderScrmServiceImpl")
     private IErpOrderService k9OrderService;
     @Autowired
+    @Qualifier("JSTErpOrderServiceImpl")
+    private IErpOrderService jSTOrderService;
+    @Autowired
     private ConfigUtil configUtil;
     @Autowired
     private IFsStoreOrderAuditLogScrmService orderAuditLogService;
@@ -102,15 +110,22 @@ public class FsStoreOrderScrmController extends BaseController {
             //判断erp类型
             Integer erpType = erpConfig.getErpType();
             if (erpType != null) {
-                if (erpType == 1) {
+                if (erpType == 1){
                     //管易
-                    erpOrderService = gyOrderService;
-                } else if (erpType == 2) {
-                    //旺店通
-                    erpOrderService = wdtOrderService;
-                } else if (erpType == 3) {
+                    erpOrderService =  gyOrderService;
+                } else if (erpType == 2){
                     //旺店通
-                    erpOrderService = k9OrderService;
+                    erpOrderService =  wdtOrderService;
+                } else if (erpType == 3){
+                    //
+                    erpOrderService =  hzOMSErpOrderService;
+                } else if (erpType == 4){
+                    //代服
+                    erpOrderService =  dfOrderService;
+                }else if(erpType == 5){
+                    erpOrderService=jSTOrderService;
+                }else if(erpType == 6){
+                    erpOrderService=k9OrderService;
                 }
             }
         }
@@ -217,7 +232,7 @@ public class FsStoreOrderScrmController extends BaseController {
     @Log(title = "订单", businessType = BusinessType.EXPORT)
     @GetMapping("/export")
     public AjaxResult export(FsStoreOrderParam param) {
-        if (param.getBeginTime().equals("") && param.getEndTime().equals("")){
+        if ("".equals(param.getBeginTime()) && "".equals(param.getEndTime())){
             param.setBeginTime(null);
             param.setEndTime(null);
         }
@@ -262,7 +277,7 @@ public class FsStoreOrderScrmController extends BaseController {
     @Log(title = "订单明细导出", businessType = BusinessType.EXPORT)
     @GetMapping("/exportItems")
     public AjaxResult exportItems(FsStoreOrderParam param) {
-        if (param.getBeginTime().equals("") && param.getEndTime().equals("")){
+        if ("".equals(param.getBeginTime()) && "".equals(param.getEndTime())){
             param.setBeginTime(null);
             param.setEndTime(null);
         }

+ 1 - 1
fs-admin/src/main/java/com/fs/hisStore/FsStoreOrderStatisticsScrmController.java → fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreOrderStatisticsScrmController.java

@@ -1,4 +1,4 @@
-package com.fs.hisStore;
+package com.fs.hisStore.controller;
 
 import com.baomidou.mybatisplus.extension.api.R;
 import com.fs.hisStore.param.FsStoreOrderStatisticsParam;

+ 1 - 1
fs-admin/src/main/java/com/fs/hisStore/FsStoreOrderStatusScrmController.java → fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreOrderStatusScrmController.java

@@ -1,4 +1,4 @@
-package com.fs.hisStore;
+package com.fs.hisStore.controller;
 
 import com.fs.common.annotation.Log;
 import com.fs.common.core.controller.BaseController;

+ 1 - 1
fs-admin/src/main/java/com/fs/hisStore/FsStorePaymentScrmController.java → fs-admin/src/main/java/com/fs/hisStore/controller/FsStorePaymentScrmController.java

@@ -1,4 +1,4 @@
-package com.fs.hisStore;
+package com.fs.hisStore.controller;
 
 import cn.hutool.json.JSONUtil;
 import com.alipay.api.AlipayApiException;

+ 1 - 1
fs-admin/src/main/java/com/fs/hisStore/FsStoreProductAttrScrmController.java → fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreProductAttrScrmController.java

@@ -1,4 +1,4 @@
-package com.fs.hisStore;
+package com.fs.hisStore.controller;
 
 import com.fs.common.annotation.Log;
 import com.fs.common.core.controller.BaseController;

+ 1 - 1
fs-admin/src/main/java/com/fs/hisStore/FsStoreProductAttrValueScrmController.java → fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreProductAttrValueScrmController.java

@@ -1,4 +1,4 @@
-package com.fs.hisStore;
+package com.fs.hisStore.controller;
 
 import com.fs.common.annotation.Log;
 import com.fs.common.core.controller.BaseController;

+ 1 - 1
fs-admin/src/main/java/com/fs/hisStore/FsStoreProductCategoryScrmController.java → fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreProductCategoryScrmController.java

@@ -1,4 +1,4 @@
-package com.fs.hisStore;
+package com.fs.hisStore.controller;
 
 import com.fs.common.annotation.Log;
 import com.fs.common.core.controller.BaseController;

+ 1 - 1
fs-admin/src/main/java/com/fs/hisStore/FsStoreProductDetailsScrmController.java → fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreProductDetailsScrmController.java

@@ -1,4 +1,4 @@
-package com.fs.hisStore;
+package com.fs.hisStore.controller;
 
 import com.fs.common.annotation.Log;
 import com.fs.common.core.controller.BaseController;

+ 1 - 1
fs-admin/src/main/java/com/fs/hisStore/FsStoreProductGroupScrmController.java → fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreProductGroupScrmController.java

@@ -1,4 +1,4 @@
-package com.fs.hisStore;
+package com.fs.hisStore.controller;
 
 import cn.hutool.json.JSONArray;
 import cn.hutool.json.JSONUtil;

+ 1 - 1
fs-admin/src/main/java/com/fs/hisStore/FsStoreProductPackageScrmController.java → fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreProductPackageScrmController.java

@@ -1,4 +1,4 @@
-package com.fs.hisStore;
+package com.fs.hisStore.controller;
 
 import cn.hutool.json.JSONArray;
 import cn.hutool.json.JSONUtil;

+ 1 - 1
fs-admin/src/main/java/com/fs/hisStore/FsStoreProductRelationScrmController.java → fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreProductRelationScrmController.java

@@ -1,4 +1,4 @@
-package com.fs.hisStore;
+package com.fs.hisStore.controller;
 
 import com.fs.common.annotation.Log;
 import com.fs.common.core.controller.BaseController;

+ 1 - 1
fs-admin/src/main/java/com/fs/hisStore/FsStoreProductReplyScrmController.java → fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreProductReplyScrmController.java

@@ -1,4 +1,4 @@
-package com.fs.hisStore;
+package com.fs.hisStore.controller;
 
 import cn.hutool.core.date.DateTime;
 import com.fs.common.annotation.Log;

+ 1 - 1
fs-admin/src/main/java/com/fs/hisStore/FsStoreProductRuleScrmController.java → fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreProductRuleScrmController.java

@@ -1,4 +1,4 @@
-package com.fs.hisStore;
+package com.fs.hisStore.controller;
 
 import cn.hutool.json.JSONUtil;
 import com.fs.common.annotation.Log;

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

@@ -1,5 +1,6 @@
-package com.fs.hisStore;
+package com.fs.hisStore.controller;
 
+import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
 import com.fs.common.annotation.Log;
 import com.fs.common.core.controller.BaseController;
 import com.fs.common.core.domain.AjaxResult;
@@ -7,6 +8,7 @@ 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.hisStore.param.FormatAttrParam;
 import com.fs.hisStore.vo.FsStoreProductAttrValueVO;
 import com.fs.hisStore.vo.FsStoreProductExportVO;
 import com.fs.hisStore.vo.FsStoreProductListVO;
@@ -22,6 +24,7 @@ import com.fs.hisStore.service.IFsStoreProductAttrValueScrmService;
 import com.fs.hisStore.service.IFsStoreProductScrmService;
 import com.mysql.cj.util.StringUtils;
 import io.swagger.annotations.ApiOperation;
+import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.HttpStatus;
 import org.springframework.http.ResponseEntity;
@@ -39,6 +42,7 @@ import java.util.List;
  * @author fs
  * @date 2022-03-15
  */
+@Slf4j
 @RestController
 @RequestMapping("/store/store/storeProduct")
 public class FsStoreProductScrmController extends BaseController
@@ -60,6 +64,7 @@ public class FsStoreProductScrmController extends BaseController
      */
     @PreAuthorize("@ss.hasPermi('store:storeProduct:list')")
     @PostMapping("/batchModify")
+    @Log(title = "商品管理", businessType = BusinessType.UPDATE,isStoreLog = true,logParam = {"商品","批量修改商品信息"})
     public R batchModify(@RequestBody ModifyMoreDTO modifyMoreDTO){
         fsStoreProductService.batchModify(modifyMoreDTO);
         return R.ok();
@@ -68,10 +73,11 @@ public class FsStoreProductScrmController extends BaseController
     /**
      * 查询商品列表
      */
-    @PreAuthorize("@ss.hasPermi('store:storeProduct:list')")
+//    @PreAuthorize("@ss.hasPermi('store:storeProduct:list')")
     @GetMapping("/list")
     public TableDataInfo list(FsStoreProductScrm fsStoreProduct)
     {
+        log.info("查询商品列表 参数: {}", fsStoreProduct);
         startPage();
         List<FsStoreProductListVO> list;
         if(StringUtils.isNullOrEmpty(fsStoreProduct.getBarCode())){
@@ -86,7 +92,7 @@ public class FsStoreProductScrmController extends BaseController
      * 导出商品列表
      */
     @PreAuthorize("@ss.hasPermi('store:storeProduct:export')")
-    @Log(title = "商品", businessType = BusinessType.EXPORT)
+    @Log(title = "商品管理", businessType = BusinessType.EXPORT, isStoreLog = true,logParam = {"商品","导出商品信息"})
     @GetMapping("/export")
     public AjaxResult export(FsStoreProductScrm fsStoreProduct)
     {
@@ -96,7 +102,7 @@ public class FsStoreProductScrmController extends BaseController
     }
 
 
-    @Log(title = "商品导入", businessType = BusinessType.IMPORT)
+    @Log(title = "商品管理", businessType = BusinessType.IMPORT,isStoreLog = true,logParam = {"商品","商品导入"})
     @PreAuthorize("@ss.hasPermi('store:storeProduct:import')")
     @PostMapping("/importData")
     public AjaxResult importData(MultipartFile file, boolean updateSupport) throws Exception
@@ -128,16 +134,21 @@ public class FsStoreProductScrmController extends BaseController
     }
 
     @PreAuthorize("@ss.hasPermi('store:storeProduct:add')")
-    @Log(title = "商品", businessType = BusinessType.INSERT)
+    @Log(title = "商品管理", businessType = BusinessType.INSERT, businessTypeExpression = "#p0.getProductId()>0? T(com.fs.common.enums.BusinessType).UPDATE: T(com.fs.common.enums.BusinessType).INSERT"
+            , isStoreLog = true, logParamExpression = "#p0.getProductId()>0? new String[]{'商品','修改商品'}: new String[]{'商品','新增商品'}")
     @PostMapping(value = "/addOrEdit")
     public R addOrEdit(@RequestBody FsStoreProductAddEditParam fsStoreProduct)
     {
-        if (fsStoreProduct.getIsShow() ==1){
-            logger.info("商品上架:{}",fsStoreProduct.getProductName()+new Date());
+        if(ObjectUtils.isNotNull(fsStoreProduct.getIsShow())) {
+            if (fsStoreProduct.getIsShow() ==1){
+                logger.info("商品上架:{}",fsStoreProduct.getProductName()+new Date());
+            }
         }
 
-        if (fsStoreProduct.getIsDisplay() ==1){
-            logger.info("商品前端展示:{}",fsStoreProduct.getProductName()+new Date());
+        if(ObjectUtils.isNotNull(fsStoreProduct.getIsDisplay())) {
+            if (fsStoreProduct.getIsDisplay() ==1){
+                logger.info("商品前端展示:{}",fsStoreProduct.getProductName()+new Date());
+            }
         }
         return fsStoreProductService.addOrEdit(fsStoreProduct);
     }
@@ -149,7 +160,8 @@ public class FsStoreProductScrmController extends BaseController
      * 删除商品
      */
     @PreAuthorize("@ss.hasPermi('store:storeProduct:remove')")
-    @Log(title = "商品", businessType = BusinessType.DELETE)
+    @Log(title = "商品管理", businessType = BusinessType.DELETE,isStoreLog = true,
+            logParamExpression ="#p0.length>1?new String[]{'商品','批量删除商品信息'}: new String[]{'商品','删除商品信息'}" )
 	@DeleteMapping("/{productIds}")
     public AjaxResult remove(@PathVariable Long[] productIds)
     {
@@ -158,8 +170,8 @@ public class FsStoreProductScrmController extends BaseController
 
     @ApiOperation(value = "生成属性")
     @PostMapping(value = "/genFormatAttr/{productId}")
-    public ResponseEntity genFormatAttr(@PathVariable Long productId, @RequestBody String jsonStr){
-        return new ResponseEntity<>(fsStoreProductService.getFormatAttr(productId,jsonStr), HttpStatus.OK);
+    public ResponseEntity genFormatAttr(@PathVariable Long productId,@RequestBody FormatAttrParam param){
+        return new ResponseEntity<>(fsStoreProductService.getFormatAttr(productId,param.getAttrs(),param.getStores()), HttpStatus.OK);
     }
 
 

+ 1 - 1
fs-admin/src/main/java/com/fs/hisStore/FsStoreProductTemplateScrmController.java → fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreProductTemplateScrmController.java

@@ -1,4 +1,4 @@
-package com.fs.hisStore;
+package com.fs.hisStore.controller;
 
 import com.fs.common.annotation.Log;
 import com.fs.common.core.controller.BaseController;

+ 134 - 0
fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreScrmController.java

@@ -0,0 +1,134 @@
+package com.fs.hisStore.controller;
+
+import com.fs.common.annotation.Log;
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.core.page.TableDataInfo;
+import com.fs.common.enums.BusinessType;
+import com.fs.common.utils.ParseUtils;
+import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.hisStore.domain.FsStoreScrm;
+import com.fs.his.param.FsStoreAuditParam;
+import com.fs.hisStore.service.IFsStoreScrmService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * 店铺管理Controller
+ *
+ * @author fs
+ * @date 2023-06-15
+ */
+@RestController
+@RequestMapping("/store/his/store")
+public class FsStoreScrmController extends BaseController
+{
+    @Autowired
+    private IFsStoreScrmService fsStoreService;
+
+    /**
+     * 查询店铺管理列表
+     */
+    @PreAuthorize("@ss.hasPermi('his:store:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(FsStoreScrm fsStore)
+    {
+        startPage();
+        List<FsStoreScrm> list = fsStoreService.selectFsStoreList(fsStore);
+        for (FsStoreScrm store : list) {
+            store.setPhone(ParseUtils.parsePhone(store.getPhone()));
+        }
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出店铺管理列表
+     */
+    @PreAuthorize("@ss.hasPermi('his:store:export')")
+    @Log(title = "店铺管理", businessType = BusinessType.EXPORT,logParam = {"店铺","导出店铺信息"},isStoreLog = true)
+    @GetMapping("/export")
+    public AjaxResult export(FsStoreScrm fsStore)
+    {
+        List<FsStoreScrm> list = fsStoreService.selectFsStoreList(fsStore);
+        for (FsStoreScrm store : list) {
+            store.setPhone(ParseUtils.parsePhone(store.getPhone()));
+        }
+        ExcelUtil<FsStoreScrm> util = new ExcelUtil<FsStoreScrm>(FsStoreScrm.class);
+        return util.exportExcel(list, "店铺管理数据");
+    }
+
+    /**
+     * 获取店铺管理详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('his:store:query')")
+    @GetMapping(value = "/{storeId}")
+    public AjaxResult getInfo(@PathVariable("storeId") Long storeId)
+    {
+        FsStoreScrm fsStore = fsStoreService.selectFsStoreByStoreId(storeId);
+        fsStore.setPhone(ParseUtils.parsePhone(fsStore.getPhone()));
+        return AjaxResult.success(fsStore);
+    }
+
+    /**
+     * 新增店铺管理
+     */
+    @PreAuthorize("@ss.hasPermi('his:store:add')")
+    @Log(title = "店铺管理", businessType = BusinessType.INSERT,logParam = {"店铺","新增店铺信息"},isStoreLog = true)
+    @PostMapping
+    public AjaxResult add(@RequestBody FsStoreScrm fsStore)
+    {
+        return toAjax(fsStoreService.insertFsStore(fsStore));
+    }
+
+    /**
+     * 修改店铺管理
+     */
+    @PreAuthorize("@ss.hasPermi('his:store:edit')")
+    @Log(title = "店铺管理", businessType = BusinessType.UPDATE,logParam = {"店铺","修改店铺信息"},isStoreLog = true)
+    @PutMapping
+    public AjaxResult edit(@RequestBody FsStoreScrm fsStore)
+    {
+
+        if (fsStore.getPhone()!=null&&fsStore.getPhone().contains("*")){
+            fsStore.setPhone(null);
+        }
+        return toAjax(fsStoreService.updateFsStore(fsStore));
+    }
+
+    /**
+     * 删除店铺管理
+     */
+    @PreAuthorize("@ss.hasPermi('his:store:remove')")
+    @Log(title = "店铺管理", businessType = BusinessType.DELETE,logParam = {"店铺","删除店铺信息"},isStoreLog = true)
+	@DeleteMapping("/{storeIds}")
+    public AjaxResult remove(@PathVariable Long[] storeIds)
+    {
+        return toAjax(fsStoreService.deleteFsStoreByStoreIds(storeIds));
+    }
+
+    /**
+     * 店铺审核
+     */
+    @PreAuthorize("@ss.hasPermi('his:store:audit')")
+    @Log(title = "店铺审核", businessType = BusinessType.UPDATE,logParam = {"店铺","店铺审核"},isStoreLog = true)
+    @PutMapping("/audit")
+    public AjaxResult audit(@RequestBody FsStoreAuditParam fsStore)
+    {
+        return toAjax(fsStoreService.updateFsStoreAudit(fsStore));
+    }
+
+    /**
+     * 重置店铺密码
+     * */
+    @PreAuthorize("@ss.hasPermi('his:store:refresh')")
+    @Log(title = "店铺管理", businessType = BusinessType.UPDATE,logParam = {"店铺","重置店铺密码"},isStoreLog = true)
+    @PutMapping("/refresh/{storeId}")
+    public AjaxResult refresh(Long storeId)
+    {
+        return toAjax(fsStoreService.refreshFsStore(storeId));
+    }
+
+}

+ 1 - 1
fs-admin/src/main/java/com/fs/hisStore/FsStoreShopScrmController.java → fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreShopScrmController.java

@@ -1,4 +1,4 @@
-package com.fs.hisStore;
+package com.fs.hisStore.controller;
 
 import com.fs.common.annotation.Log;
 import com.fs.common.core.controller.BaseController;

+ 1 - 1
fs-admin/src/main/java/com/fs/hisStore/FsStoreShopStaffScrmController.java → fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreShopStaffScrmController.java

@@ -1,4 +1,4 @@
-package com.fs.hisStore;
+package com.fs.hisStore.controller;
 
 import com.fs.common.annotation.Log;
 import com.fs.common.core.controller.BaseController;

+ 1 - 1
fs-admin/src/main/java/com/fs/hisStore/FsStoreStatisticsScrmController.java → fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreStatisticsScrmController.java

@@ -1,4 +1,4 @@
-package com.fs.hisStore;
+package com.fs.hisStore.controller;
 
 import com.alibaba.fastjson.JSONObject;
 import com.fs.common.core.controller.BaseController;

+ 1 - 1
fs-admin/src/main/java/com/fs/hisStore/FsStoreVisitScrmController.java → fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreVisitScrmController.java

@@ -1,4 +1,4 @@
-package com.fs.hisStore;
+package com.fs.hisStore.controller;
 
 import com.fs.common.annotation.Log;
 import com.fs.common.core.controller.BaseController;

+ 50 - 0
fs-admin/src/main/java/com/fs/hisStore/controller/SysOperlogScrmController.java

@@ -0,0 +1,50 @@
+package com.fs.hisStore.controller;
+
+import com.fs.common.annotation.Log;
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.core.page.TableDataInfo;
+import com.fs.common.enums.BusinessType;
+import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.hisStore.service.ISysOperLogScrmService;
+import com.fs.hisStore.domain.SysOperLogScrm;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * 操作日志记录
+ *
+
+ */
+@RestController
+@RequestMapping("/store/operlogScrm")
+public class SysOperlogScrmController extends BaseController
+{
+    private final ISysOperLogScrmService operLogService;
+
+    public SysOperlogScrmController(ISysOperLogScrmService operLogService) {
+        this.operLogService = operLogService;
+    }
+
+    @PreAuthorize("@ss.hasPermi('his:storeLog:export')")
+    @GetMapping("/list")
+    public TableDataInfo list(SysOperLogScrm operLog)
+    {
+        startPage();
+        List<SysOperLogScrm> list = operLogService.selectOperLogList(operLog);
+        return getDataTable(list);
+    }
+
+    @Log(title = "操作日志", businessType = BusinessType.EXPORT)
+    @PreAuthorize("@ss.hasPermi('his:storeLog:export')")
+    @GetMapping("/export")
+    public AjaxResult export(SysOperLogScrm operLog)
+    {
+        List<SysOperLogScrm> list = operLogService.selectOperLogList(operLog);
+        ExcelUtil<SysOperLogScrm> util = new ExcelUtil<>(SysOperLogScrm.class);
+        return util.exportExcel(list, "操作日志");
+    }
+
+}

+ 1 - 1
fs-service/src/main/java/com/fs/task/CrmTask.java → fs-admin/src/main/java/com/fs/hisStore/task/CrmTask.java

@@ -1,4 +1,4 @@
-package com.fs.task;
+package com.fs.hisStore.task;
 
 import com.fs.crm.service.ICrmCustomerService;
 import lombok.extern.slf4j.Slf4j;

+ 1 - 1
fs-service/src/main/java/com/fs/task/ErpTask.java → fs-admin/src/main/java/com/fs/hisStore/task/ErpTask.java

@@ -1,4 +1,4 @@
-package com.fs.task;
+package com.fs.hisStore.task;
 
 import com.fs.erp.domain.ErpOrder;
 import com.fs.erp.domain.FsErpFinishPush;

+ 92 - 5
fs-service/src/main/java/com/fs/task/StoreTask.java → fs-admin/src/main/java/com/fs/hisStore/task/MallStoreTask.java

@@ -1,4 +1,4 @@
-package com.fs.task;
+package com.fs.hisStore.task;
 
 
 import cn.hutool.core.util.StrUtil;
@@ -21,8 +21,8 @@ import com.fs.his.dto.ExpressInfoDTO;
 import com.fs.his.service.IFsExpressService;
 import com.fs.his.service.IFsUserService;
 import com.fs.his.utils.ConfigUtil;
-import com.fs.hisStore.config.FsErpConfig;
 import com.fs.hisStore.domain.*;
+import com.fs.hisStore.dto.DateComparisonConfigDTO;
 import com.fs.hisStore.enums.ShipperCodeEnum;
 import com.fs.hisStore.mapper.FsStoreOrderItemScrmMapper;
 import com.fs.hisStore.mapper.FsStoreOrderScrmMapper;
@@ -35,16 +35,20 @@ import com.fs.pay.service.IPayService;
 import com.fs.store.config.StoreConfig;
 import com.fs.system.service.ISysConfigService;
 import com.fs.ybPay.domain.OrderResult;
+import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Qualifier;
 import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.jdbc.core.JdbcTemplate;
 import org.springframework.stereotype.Component;
 
 import java.math.BigDecimal;
 import java.text.ParseException;
+import java.time.LocalTime;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Map;
 
 import static com.fs.hisStore.constants.StoreConstants.DELIVERY;
 
@@ -53,8 +57,9 @@ import static com.fs.hisStore.constants.StoreConstants.DELIVERY;
  *
  * @author fs
  */
+@Slf4j
 @Component("mallStoreTask")
-public class StoreTask
+public class MallStoreTask
 {
     @Autowired
     private RedisTemplate redisTemplate;
@@ -68,8 +73,6 @@ public class StoreTask
     private IFsStoreAfterSalesScrmService afterSalesService;
     @Autowired
     private IFsUserService userService;
-
-
     @Autowired
     private IPayService ybPayService;
     @Autowired
@@ -128,6 +131,10 @@ public class StoreTask
     @Qualifier("JSTErpOrderServiceImpl")
     private IErpOrderService jSTOrderService;
 
+    @Autowired
+    @Qualifier("k9OrderScrmServiceImpl")
+    private IErpOrderService k9OrderService;
+
     @Autowired
     private ConfigUtil configUtil;
 
@@ -473,6 +480,8 @@ public class StoreTask
                     erpOrderService = dfOrderService;
                 } else if (erpType == 5) {
                     erpOrderService = jSTOrderService;
+                }else if (erpType == 6) {
+                    erpOrderService = k9OrderService;
                 }
             }
         }
@@ -504,4 +513,82 @@ public class StoreTask
         fsUserOnlineStateService.insertUserNotOnline();
     }*/
 
+    /**
+     * 提醒证件到期任务
+     * */
+    @Autowired
+    private JdbcTemplate jdbcTemplate;
+    public void remindCertValidation() {
+        log.info("提醒店铺证件到期任务执行... 当前时间: {}", LocalTime.now());
+
+        // 从配置表获取需要比较的表和字段
+        List<DateComparisonConfigDTO> tablesToCheck = jdbcTemplate.query(
+                "SELECT table_name, date_column,in_advance,user_column,phone_column,remind_words,platform,cert_type" +
+                        " FROM date_comparison_config",(rs, rowNum)->{
+                    return DateComparisonConfigDTO.builder()
+                            .tableName(rs.getString("table_name"))//表名
+                            .certType(rs.getString("cert_type"))//证件类型
+                            .dateColumn(rs.getString("date_column"))//日期字段
+                            .userColumn(rs.getString("user_column"))//用户字段
+                            .remindWords(rs.getString("remindWords"))//提醒内容
+                            .phoneColumn(rs.getString("phone_column"))//提醒手机
+                            .inAdvance(rs.getInt("inAdvance"))//提前天数
+                            .platform(rs.getString("platform")).build();//平台
+                });
+
+        tablesToCheck.forEach(dto -> {
+            //获取证件失效日期字段小于当前时间加提前天数的用户和电话号码
+            String sql = String.format("SELECT %s , %s " +
+                            "FROM %s " +
+                            "WHERE %s >= DATE_SUB(CURDATE(), INTERVAL %d DAY)",
+                            dto.getUserColumn(),
+                            dto.getPhoneColumn(),
+                            dto.getTableName(),
+                            dto.getDateColumn(),
+                            dto.getInAdvance()
+                            );
+            List<Map<String, Object>> users = jdbcTemplate.queryForList(sql);
+            users.forEach(user -> {
+                String userName = (String) user.get(dto.getUserColumn());
+                String phone = (String) user.get(dto.getPhoneColumn());
+                String remindWords = String.format("【%s平台提示】尊敬的%s用户,店铺%s证件即将到期,请及时处理!",
+                        dto.getPlatform(),
+                        userName,
+                        dto.getCertType());
+                // 使用phone发送remindWords短信
+                // TODO 发送通知
+            });
+        });
+
+    }
+
+    /**
+     * 禁用店铺
+     * */
+    public void disable() {
+        log.info("禁用店铺任务执行... 当前时间: {}", LocalTime.now());
+        // 从配置表获取需要禁用的表和字段
+        List<DateComparisonConfigDTO> toDisable = jdbcTemplate.query(
+                "SELECT table_name, date_column,invalid_expression,status_column" +
+                        " FROM date_comparison_config " +
+                        " WHERE is_do_invalid = '1'",(rs, rowNum)-> DateComparisonConfigDTO.builder()
+                                .tableName(rs.getString("table_name"))//表名
+                                .dateColumn(rs.getString("date_column"))//日期字段
+                                .invalidExpression(rs.getString("invalid_expression"))//失效表达式
+                                .statusColumn(rs.getString("status_column"))//状态字段
+                                .build());
+
+        toDisable.forEach(dto -> {
+            //更新证件失效日期字段小于当前时间的数据
+            String sql = String.format("UPDATE %s " +
+                    "SET %s = %s " +
+                    "WHERE %s < CURDATE()",
+                    dto.getTableName(),
+                    dto.getStatusColumn(),
+                    dto.getInvalidExpression(),
+                    dto.getDateColumn());
+            jdbcTemplate.update(sql);
+        });
+    }
+
 }

+ 1 - 1
fs-service/src/main/java/com/fs/task/stats/FsStatsMemberDailyTask.java → fs-admin/src/main/java/com/fs/hisStore/task/stats/FsStatsMemberDailyTask.java

@@ -1,4 +1,4 @@
-package com.fs.task.stats;
+package com.fs.hisStore.task.stats;
 
 import com.fs.statis.service.IFsStatsMemberDailyService;
 import lombok.extern.slf4j.Slf4j;

+ 155 - 0
fs-admin/src/main/java/com/fs/medical/MeasurementUnitController.java

@@ -0,0 +1,155 @@
+package com.fs.medical;
+
+import com.fs.common.annotation.RepeatSubmit;
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.R;
+import com.fs.medical.domain.MeasurementUnit;
+import com.fs.medical.param.MeasurementUnitQueryDto;
+import com.fs.medical.service.MeasurementUnitService;
+import com.github.pagehelper.PageHelper;
+import com.github.pagehelper.PageInfo;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * 计量单位Controller
+ *
+ * @author fs
+ * @date 2024
+ */
+@Api("计量单位")
+@RestController
+@RequestMapping("/admin/medical/unit")
+public class MeasurementUnitController extends BaseController {
+    private final Logger logger = LoggerFactory.getLogger(this.getClass());
+
+    @Autowired
+    private MeasurementUnitService measurementUnitService;
+
+    /**
+     * 查询所有计量单位
+     */
+    @ApiOperation("查询所有计量单位")
+    @GetMapping("/listAll")
+    public R listAll() {
+        try {
+            List<MeasurementUnit> list = measurementUnitService.listAll();
+            return R.ok().put("data",list);
+        } catch (Exception e) {
+            logger.error("查询计量单位失败", e);
+            return R.error("查询失败");
+        }
+    }
+
+    /**
+     * 分页查询计量单位列表(带筛选)
+     */
+    @ApiOperation("分页查询计量单位列表")
+    @GetMapping("/page")
+    public R page(MeasurementUnitQueryDto queryDto) {
+        try {
+            PageHelper.startPage(queryDto.getPageNum(), queryDto.getPageSize());
+            List<MeasurementUnit> list = measurementUnitService.selectPageList(queryDto);
+            PageInfo<MeasurementUnit> pageInfo = new PageInfo<>(list);
+            return R.ok().put("data", pageInfo);
+        } catch (Exception e) {
+            logger.error("分页查询计量单位失败", e);
+            return R.error("查询失败");
+        }
+    }
+
+    /**
+     * 根据单位类型查询计量单位
+     */
+    @ApiOperation("根据单位类型查询计量单位")
+    @GetMapping("/listByType")
+    public R listByType(@RequestParam String unitType) {
+        try {
+            List<MeasurementUnit> list = measurementUnitService.listByType(unitType);
+            return R.ok().put("data",list);
+        } catch (Exception e) {
+            logger.error("根据类型查询计量单位失败", e);
+            return R.error("查询失败");
+        }
+    }
+
+    /**
+     * 根据ID查询计量单位详情
+     */
+    @ApiOperation("根据ID查询计量单位详情")
+    @GetMapping("/{unitId}")
+    public R getById(@PathVariable("unitId") Long unitId) {
+        try {
+            MeasurementUnit unit = measurementUnitService.getById(unitId);
+            return R.ok().put("data",unit);
+        } catch (Exception e) {
+            logger.error("查询计量单位详情失败", e);
+            return R.error("查询失败");
+        }
+    }
+
+    /**
+     * 新增计量单位
+     */
+    @RepeatSubmit
+    @ApiOperation("新增计量单位")
+    @PostMapping("/add")
+    public R add(@RequestBody MeasurementUnit unit) {
+        try {
+            boolean result = measurementUnitService.save(unit);
+            if (result) {
+                return R.ok("新增成功");
+            } else {
+                return R.error("新增失败");
+            }
+        } catch (Exception e) {
+            logger.error("新增计量单位失败", e);
+            return R.error("新增失败");
+        }
+    }
+
+    /**
+     * 更新计量单位
+     */
+    @RepeatSubmit
+    @ApiOperation("更新计量单位")
+    @PutMapping("/update")
+    public R update(@RequestBody MeasurementUnit unit) {
+        try {
+            boolean result = measurementUnitService.update(unit);
+            if (result) {
+                return R.ok("更新成功");
+            } else {
+                return R.error("更新失败");
+            }
+        } catch (Exception e) {
+            logger.error("更新计量单位失败", e);
+            return R.error("更新失败");
+        }
+    }
+
+    /**
+     * 删除计量单位
+     */
+    @ApiOperation("删除计量单位")
+    @DeleteMapping("/{unitId}")
+    public R delete(@PathVariable("unitId") Long unitId) {
+        try {
+            boolean result = measurementUnitService.deleteById(unitId);
+            if (result) {
+                return R.ok("删除成功");
+            } else {
+                return R.error("删除失败");
+            }
+        } catch (Exception e) {
+            logger.error("删除计量单位失败", e);
+            return R.error("删除失败");
+        }
+    }
+}

+ 157 - 0
fs-admin/src/main/java/com/fs/medical/MedicalIndicatorController.java

@@ -0,0 +1,157 @@
+package com.fs.medical;
+
+import com.fs.common.annotation.RepeatSubmit;
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.R;
+import com.fs.medical.domain.MedicalIndicator;
+import com.fs.medical.param.MedicalIndicatorQueryDto;
+import com.fs.medical.service.MedicalIndicatorService;
+import com.github.pagehelper.PageHelper;
+import com.github.pagehelper.PageInfo;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.extern.slf4j.Slf4j;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * 医疗指标Controller
+ *
+ * @author fs
+ * @date 2024
+ */
+@Slf4j
+@Api("医疗指标")
+@RestController
+@RequestMapping("/admin/medical/indicator")
+public class MedicalIndicatorController extends BaseController {
+    private final Logger logger = LoggerFactory.getLogger(this.getClass());
+
+    @Autowired
+    private MedicalIndicatorService medicalIndicatorService;
+
+    /**
+     * 查询所有启用的指标
+     */
+    @ApiOperation("查询所有启用的指标")
+    @GetMapping("/listEnabled")
+    public R listAllEnabled() {
+        try {
+            List<MedicalIndicator> list = medicalIndicatorService.listAllEnabled();
+            return R.ok().put("data",list);
+        } catch (Exception e) {
+            logger.error("查询启用指标失败", e);
+            return R.error("查询失败");
+        }
+    }
+
+    /**
+     * 分页查询医疗指标列表(带筛选)
+     */
+    @ApiOperation("分页查询医疗指标列表")
+    @GetMapping("/page")
+    public R page(MedicalIndicatorQueryDto queryDto) {
+        try {
+            PageHelper.startPage(queryDto.getPageNum(), queryDto.getPageSize());
+            List<MedicalIndicator> list = medicalIndicatorService.selectPageList(queryDto);
+            PageInfo<MedicalIndicator> pageInfo = new PageInfo<>(list);
+            return R.ok().put("data", pageInfo);
+        } catch (Exception e) {
+            logger.error("分页查询医疗指标失败", e);
+            return R.error("查询失败");
+        }
+    }
+
+    /**
+     * 根据分类查询指标
+     */
+    @ApiOperation("根据分类查询指标")
+    @GetMapping("/listByCategory")
+    public R listByCategory(@RequestParam String category) {
+        try {
+            List<MedicalIndicator> list = medicalIndicatorService.listByCategory(category);
+            return R.ok().put("data",list);
+        } catch (Exception e) {
+            logger.error("根据分类查询指标失败", e);
+            return R.error("查询失败");
+        }
+    }
+
+    /**
+     * 根据ID查询指标详情
+     */
+    @ApiOperation("根据ID查询指标详情")
+    @GetMapping("/{indicatorId}")
+    public R getById(@PathVariable("indicatorId") Long indicatorId) {
+        try {
+            MedicalIndicator indicator = medicalIndicatorService.getById(indicatorId);
+            return R.ok().put("data",indicator);
+        } catch (Exception e) {
+            logger.error("查询指标详情失败", e);
+            return R.error("查询失败");
+        }
+    }
+
+    /**
+     * 新增指标
+     */
+    @RepeatSubmit
+    @ApiOperation("新增指标")
+    @PostMapping("/add")
+    public R add(@RequestBody MedicalIndicator indicator) {
+        try {
+            boolean result = medicalIndicatorService.save(indicator);
+            if (result) {
+                return R.ok("新增成功");
+            } else {
+                return R.error("新增失败");
+            }
+        } catch (Exception e) {
+            logger.error("新增指标失败", e);
+            return R.error("新增失败");
+        }
+    }
+
+    /**
+     * 更新指标
+     */
+    @RepeatSubmit
+    @ApiOperation("更新指标")
+    @PutMapping("/update")
+    public R update(@RequestBody MedicalIndicator indicator) {
+        try {
+            boolean result = medicalIndicatorService.update(indicator);
+            if (result) {
+                return R.ok("更新成功");
+            } else {
+                return R.error("更新失败");
+            }
+        } catch (Exception e) {
+            logger.error("更新指标失败", e);
+            return R.error("更新失败");
+        }
+    }
+
+    /**
+     * 删除指标
+     */
+    @ApiOperation("删除指标")
+    @DeleteMapping("/{indicatorId}")
+    public R delete(@PathVariable("indicatorId") Long indicatorId) {
+        try {
+            boolean result = medicalIndicatorService.deleteById(indicatorId);
+            if (result) {
+                return R.ok("删除成功");
+            } else {
+                return R.error("删除失败");
+            }
+        } catch (Exception e) {
+            logger.error("删除指标失败", e);
+            return R.error("删除失败");
+        }
+    }
+}

+ 160 - 0
fs-admin/src/main/java/com/fs/medical/PhysicalExamReportController.java

@@ -0,0 +1,160 @@
+package com.fs.medical;
+
+import com.fs.common.annotation.RepeatSubmit;
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.R;
+import com.fs.medical.domain.PhysicalExamReport;
+import com.fs.medical.param.PhysicalExamReportCompareDto;
+import com.fs.medical.param.PhysicalExamReportQueryDto;
+import com.fs.medical.service.PhysicalExamReportService;
+import com.github.pagehelper.PageHelper;
+import com.github.pagehelper.PageInfo;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.format.annotation.DateTimeFormat;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.Date;
+import java.util.List;
+
+/**
+ * 体检报告Controller
+ *
+ * @author fs
+ * @date 2024
+ */
+@Api("体检报告")
+@RestController
+@RequestMapping("/admin/medical/report")
+public class PhysicalExamReportController extends BaseController {
+    private final Logger logger = LoggerFactory.getLogger(this.getClass());
+
+    @Autowired
+    private PhysicalExamReportService physicalExamReportService;
+
+    /**
+     * 根据用户ID查询体检报告列表
+     */
+    @ApiOperation("查询用户体检报告列表")
+    @GetMapping("/listByUser/{userId}")
+    public R listByUserId(@PathVariable("userId") Long userId) {
+        try {
+            List<PhysicalExamReport> list = physicalExamReportService.listByUserId(userId);
+            return R.ok().put("data",list);
+        } catch (Exception e) {
+            logger.error("查询用户体检报告失败", e);
+            return R.error("查询失败");
+        }
+    }
+
+    /**
+     * 分页查询体检报告列表(带筛选)
+     */
+    @ApiOperation("分页查询体检报告列表")
+    @GetMapping("/page")
+    public R page(PhysicalExamReportQueryDto queryDto) {
+        try {
+            PageHelper.startPage(queryDto.getPageNum(), queryDto.getPageSize());
+            List<PhysicalExamReport> list = physicalExamReportService.selectPageList(queryDto);
+            PageInfo<PhysicalExamReport> pageInfo = new PageInfo<>(list);
+            return R.ok().put("data", pageInfo);
+        } catch (Exception e) {
+            logger.error("分页查询体检报告失败", e);
+            return R.error("查询失败");
+        }
+    }
+
+    /**
+     * 根据用户ID和体检日期查询体检报告
+     */
+    @ApiOperation("根据用户ID和体检日期查询体检报告")
+    @GetMapping("/getByUserAndDate")
+    public R getByUserIdAndDate(
+            @RequestParam Long userId,
+            @RequestParam @DateTimeFormat(pattern = "yyyy-MM-dd") Date examDate) {
+        try {
+            PhysicalExamReport report = physicalExamReportService.getByUserIdAndDate(userId, examDate);
+            return R.ok().put("data",report);
+        } catch (Exception e) {
+            logger.error("根据用户ID和日期查询体检报告失败", e);
+            return R.error("查询失败");
+        }
+    }
+
+    /**
+     * 根据ID查询体检报告详情
+     */
+    @ApiOperation("查询体检报告详情")
+    @GetMapping("/{reportId}")
+    public R getById(@PathVariable("reportId") Long reportId) {
+        try {
+            PhysicalExamReport report = physicalExamReportService.getById(reportId);
+            return R.ok().put("data",report);
+        } catch (Exception e) {
+            logger.error("查询体检报告详情失败", e);
+            return R.error("查询失败");
+        }
+    }
+
+    /**
+     * 新增体检报告
+     */
+    @RepeatSubmit
+    @ApiOperation("新增体检报告")
+    @PostMapping("/add")
+    public R add(@RequestBody PhysicalExamReport report) {
+        try {
+            boolean result = physicalExamReportService.save(report);
+            if (result) {
+                return R.ok("新增成功");
+            } else {
+                return R.error("新增失败");
+            }
+        } catch (Exception e) {
+            logger.error("新增体检报告失败", e);
+            return R.error("新增失败");
+        }
+    }
+
+    /**
+     * 更新体检报告
+     */
+    @RepeatSubmit
+    @ApiOperation("更新体检报告")
+    @PutMapping("/update")
+    public R update(@RequestBody PhysicalExamReport report) {
+        try {
+            boolean result = physicalExamReportService.update(report);
+            if (result) {
+                return R.ok("更新成功");
+            } else {
+                return R.error("更新失败");
+            }
+        } catch (Exception e) {
+            logger.error("更新体检报告失败", e);
+            return R.error("更新失败");
+        }
+    }
+
+    /**
+     * 删除体检报告
+     */
+    @ApiOperation("删除体检报告")
+    @DeleteMapping("/{reportId}")
+    public R delete(@PathVariable("reportId") Long reportId) {
+        try {
+            boolean result = physicalExamReportService.deleteById(reportId);
+            if (result) {
+                return R.ok("删除成功");
+            } else {
+                return R.error("删除失败");
+            }
+        } catch (Exception e) {
+            logger.error("删除体检报告失败", e);
+            return R.error("删除失败");
+        }
+    }
+}

+ 190 - 0
fs-admin/src/main/java/com/fs/medical/ReportIndicatorResultController.java

@@ -0,0 +1,190 @@
+package com.fs.medical;
+
+import com.fs.common.annotation.RepeatSubmit;
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.R;
+import com.fs.medical.domain.ReportIndicatorResult;
+import com.fs.medical.dto.ReportAllIndicatorCateDTO;
+import com.fs.medical.param.ReportIndicatorResultQueryDto;
+import com.fs.medical.service.ReportIndicatorResultService;
+import com.github.pagehelper.PageHelper;
+import com.github.pagehelper.PageInfo;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * 报告指标检查Controller
+ *
+ * @author fs
+ * @date 2024
+ */
+@Api("报告指标检查")
+@RestController
+@RequestMapping("/admin/medical/result")
+public class ReportIndicatorResultController extends BaseController {
+    private final Logger logger = LoggerFactory.getLogger(this.getClass());
+
+    @Autowired
+    private ReportIndicatorResultService reportIndicatorResultService;
+
+    /**
+     * 根据报告ID查询所有指标结果
+     */
+    @ApiOperation("根据报告ID查询所有指标结果")
+    @GetMapping("/listByReport/{reportId}")
+    public R listByReportId(@PathVariable("reportId") Long reportId) {
+        try {
+            List<ReportIndicatorResult> list = reportIndicatorResultService.listByReportId(reportId);
+            return R.ok().put("data",list);
+        } catch (Exception e) {
+            logger.error("根据报告ID查询指标结果失败", e);
+            return R.error("查询失败");
+        }
+    }
+
+    @ApiOperation("获取指定报告的指标分类")
+    @GetMapping("/getAllCateByReportId")
+    public R getAllIndicatorByReportId(@RequestParam("reportId") Long reportId) {
+        List<ReportAllIndicatorCateDTO> allIndicatorByReportId = reportIndicatorResultService.getAllIndicatorByReportId(reportId);
+        return R.ok().put("data",allIndicatorByReportId);
+    }
+
+    /**
+     * 分页查询报告指标检查结果列表(带筛选)
+     */
+    @ApiOperation("分页查询报告指标检查结果列表")
+    @GetMapping("/page")
+    public R page(ReportIndicatorResultQueryDto queryDto) {
+        try {
+            PageHelper.startPage(queryDto.getPageNum(), queryDto.getPageSize());
+            List<ReportIndicatorResult> list = reportIndicatorResultService.selectPageList(queryDto);
+            PageInfo<ReportIndicatorResult> pageInfo = new PageInfo<>(list);
+            return R.ok().put("data", pageInfo);
+        } catch (Exception e) {
+            logger.error("分页查询报告指标检查结果失败", e);
+            return R.error("查询失败");
+        }
+    }
+
+    /**
+     * 根据指标ID查询所有结果
+     */
+    @ApiOperation("根据指标ID查询所有结果")
+    @GetMapping("/listByIndicator/{indicatorId}")
+    public R listByIndicatorId(@PathVariable("indicatorId") Long indicatorId) {
+        try {
+            List<ReportIndicatorResult> list = reportIndicatorResultService.listByIndicatorId(indicatorId);
+            return R.ok().put("data",list);
+        } catch (Exception e) {
+            logger.error("根据指标ID查询结果失败", e);
+            return R.error("查询失败");
+        }
+    }
+
+    /**
+     * 根据ID查询检查结果详情
+     */
+    @ApiOperation("查询检查结果详情")
+    @GetMapping("/{resultId}")
+    public R getById(@PathVariable("resultId") Long resultId) {
+        try {
+            ReportIndicatorResult result = reportIndicatorResultService.getById(resultId);
+            return R.ok().put("data",result);
+        } catch (Exception e) {
+            logger.error("查询检查结果详情失败", e);
+            return R.error("查询失败");
+        }
+    }
+
+    /**
+     * 新增检查结果
+     */
+    @RepeatSubmit
+    @ApiOperation("新增检查结果")
+    @PostMapping("/add")
+    public R add(@RequestBody ReportIndicatorResult result) {
+        try {
+            boolean success = reportIndicatorResultService.save(result);
+            if (success) {
+                return R.ok("新增成功");
+            } else {
+                return R.error("新增失败");
+            }
+        } catch (Exception e) {
+            logger.error("新增检查结果失败", e);
+            return R.error("新增失败");
+        }
+    }
+
+    /**
+     * 批量新增检查结果
+     */
+    @RepeatSubmit
+    @ApiOperation("批量新增检查结果")
+    @PostMapping("/batchAdd")
+    public R batchAdd(@RequestBody List<ReportIndicatorResult> results) {
+        try {
+            int successCount = 0;
+            for (ReportIndicatorResult result : results) {
+                if (reportIndicatorResultService.save(result)) {
+                    successCount++;
+                }
+            }
+            if (successCount == results.size()) {
+                return R.ok("批量新增成功");
+            } else {
+                return R.ok("部分新增成功,成功" + successCount + "条");
+            }
+        } catch (Exception e) {
+            logger.error("批量新增检查结果失败", e);
+            return R.error("批量新增失败"
+
+            );
+        }
+    }
+
+    /**
+     * 更新检查结果
+     */
+    @RepeatSubmit
+    @ApiOperation("更新检查结果")
+    @PutMapping("/update")
+    public R update(@RequestBody ReportIndicatorResult result) {
+        try {
+            boolean success = reportIndicatorResultService.update(result);
+            if (success) {
+                return R.ok("更新成功");
+            } else {
+                return R.error("更新失败");
+            }
+        } catch (Exception e) {
+            logger.error("更新检查结果失败", e);
+            return R.error("更新失败");
+        }
+    }
+
+    /**
+     * 删除检查结果
+     */
+    @ApiOperation("删除检查结果")
+    @DeleteMapping("/{resultId}")
+    public R delete(@PathVariable("resultId") Long resultId) {
+        try {
+            boolean success = reportIndicatorResultService.deleteById(resultId);
+            if (success) {
+                return R.ok("删除成功");
+            } else {
+                return R.error("删除失败");
+            }
+        } catch (Exception e) {
+            logger.error("删除检查结果失败", e);
+            return R.error("删除失败");
+        }
+    }
+}

+ 39 - 3
fs-admin/src/main/java/com/fs/qw/controller/QwExternalContactController.java

@@ -3,11 +3,13 @@ package com.fs.qw.controller;
 import java.util.List;
 import java.util.Objects;
 
+import cn.hutool.core.collection.CollectionUtil;
 import cn.hutool.core.util.ObjectUtil;
 import com.fs.common.exception.ServiceException;
 import com.fs.qw.param.QwExternalContactParam;
 import com.fs.qw.param.QwTagSearchParam;
 import com.fs.qw.service.IQwTagService;
+import com.fs.qw.vo.QwExternalContactUnionIdExportVO;
 import com.fs.qw.vo.QwExternalContactVO;
 import com.google.gson.Gson;
 import com.google.gson.reflect.TypeToken;
@@ -86,13 +88,47 @@ public class QwExternalContactController extends BaseController
     @PreAuthorize("@ss.hasPermi('qw:externalContact:export')")
     @Log(title = "企业微信客户", businessType = BusinessType.EXPORT)
     @GetMapping("/export")
-    public AjaxResult export(QwExternalContact qwExternalContact)
+    public AjaxResult export(QwExternalContactParam qwExternalContact)
     {
-        List<QwExternalContact> list = qwExternalContactService.selectQwExternalContactList(qwExternalContact);
-        ExcelUtil<QwExternalContact> util = new ExcelUtil<QwExternalContact>(QwExternalContact.class);
+        if (qwExternalContact.getCompanyId() == null) {
+            return AjaxResult.success();
+        }
+
+        List<QwExternalContactVO> list = qwExternalContactService.selectQwExternalContactListVO(qwExternalContact);
+        list.forEach(item->{
+
+            if (!Objects.equals(item.getTagIds(), "[]") && item.getTagIds()!=null) {
+                QwTagSearchParam param = new QwTagSearchParam();
+                Gson gson = new Gson();
+                List<String> tagIds = gson.fromJson(
+                        item.getTagIds(),
+                        new TypeToken<List<String>>() {
+                        }.getType()
+                );
+
+                param.setTagIds(tagIds);
+
+                item.setTagIdsName(iQwTagService.selectQwTagListByTagIds(param));
+            }
+        });
+        ExcelUtil<QwExternalContactVO> util = new ExcelUtil<QwExternalContactVO>(QwExternalContactVO.class);
         return util.exportExcel(list, "企业微信客户数据");
     }
 
+    /**
+     * 导出企业微信客户unionId
+     */
+    @PreAuthorize("@ss.hasPermi('qw:externalContact:export')")
+    @Log(title = "企业微信客户unionId", businessType = BusinessType.EXPORT)
+    @GetMapping("/exportUnionId")
+    public AjaxResult exportUnionId(QwExternalContactParam qwExternalContact)
+    {
+        List<QwExternalContactUnionIdExportVO> list = qwExternalContactService.selectQwExternalContactUnionIdExportVO(qwExternalContact);
+        ExcelUtil<QwExternalContactUnionIdExportVO> util = new ExcelUtil<QwExternalContactUnionIdExportVO>(QwExternalContactUnionIdExportVO.class);
+        return util.exportExcel(list, "企业微信客户unionId数据");
+    }
+
+
     /**
      * 获取企业微信客户详细信息
      */

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

@@ -134,7 +134,7 @@ public class QwSopTempController extends BaseController
         if(qwSopTemp.getSendType() == 11){
             //筛选选课程数据
             if(ObjectUtils.isNotNull(qwSopTemp.getTimeList()) && !qwSopTemp.getTimeList().isEmpty()){
-                qwSopTemp.setTimeList(new ArrayList<>(qwSopTemp.getTimeList().stream().filter(t->ObjectUtils.isNotNull(t) && !t.isEmpty()).collect(Collectors.toSet())));
+                qwSopTemp.setTimeList(new ArrayList<>(qwSopTemp.getTimeList().stream().filter(t->ObjectUtils.isNotNull(t) && !t.isEmpty()).collect(Collectors.toList())));
             }
             new Thread(() -> qwSopTempService.createSopTempRules(qwSopTemp)).start();
         }

+ 82 - 0
fs-admin/src/main/java/com/fs/saler/CompetitorInfoController.java

@@ -0,0 +1,82 @@
+package com.fs.saler;
+
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.R;
+import com.fs.saler.domain.FsCompetitorInfo;
+import com.fs.saler.param.FsCompetitorInfoParam;
+import com.fs.saler.service.FsCompetitorInfoService;
+import com.github.pagehelper.PageHelper;
+import com.github.pagehelper.PageInfo;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.List;
+
+/**
+ * 竞品信息控制器
+ */
+@Api("竞品信息")
+@RestController
+@RequestMapping(value="/saler/competitorInfo")
+public class CompetitorInfoController extends BaseController {
+
+    @Autowired
+    private FsCompetitorInfoService competitorInfoService;
+
+    /**
+     * 分页查询竞品列表
+     */
+    @ApiOperation("查看竞品列表")
+    @PostMapping("/listPage")
+    public R listPage(@RequestBody FsCompetitorInfoParam param) {
+        PageHelper.startPage(param.getPageNum(), param.getPageSize());
+        List<FsCompetitorInfo> list = competitorInfoService.getAll(param);
+        PageInfo<FsCompetitorInfo> pageInfo = new PageInfo<>(list);
+        return R.ok().put("data", pageInfo);
+    }
+
+    /**
+     * 查看竞品详情
+     */
+    @ApiOperation("查看竞品详情")
+    @PostMapping("/findById")
+    public R findById(@RequestBody FsCompetitorInfoParam param) {
+        FsCompetitorInfo competitorInfo = competitorInfoService.getById(param.getId());
+        return R.ok().put("data", competitorInfo);
+    }
+
+    /**
+     * 新增竞品
+     */
+    @ApiOperation("新增竞品")
+    @PostMapping("/save")
+    public R save(@RequestBody FsCompetitorInfo competitorInfo) {
+        boolean result = competitorInfoService.save(competitorInfo);
+        return result ? R.ok() : R.error("新增竞品失败");
+    }
+
+    /**
+     * 更新竞品信息
+     */
+    @ApiOperation("更新竞品信息")
+    @PostMapping("/updateById")
+    public R updateById(@RequestBody FsCompetitorInfo competitorInfo) {
+        boolean result = competitorInfoService.update(competitorInfo);
+        return result ? R.ok() : R.error("更新竞品信息失败");
+    }
+
+    /**
+     * 删除竞品
+     */
+    @ApiOperation("删除竞品")
+    @PostMapping("/deleteById")
+    public R deleteById(@RequestBody FsCompetitorInfoParam param) {
+        boolean result = competitorInfoService.removeById(param.getId());
+        return result ? R.ok() : R.error("删除竞品失败");
+    }
+}

+ 73 - 0
fs-admin/src/main/java/com/fs/saler/FsServiceGoodsController.java

@@ -0,0 +1,73 @@
+package com.fs.saler;
+
+import com.fs.common.core.domain.R;
+import com.fs.saler.domain.FsProductInfo;
+import com.fs.saler.param.ProductInfoListPageParam;
+import com.fs.saler.service.FsProductInfoService;
+import com.github.pagehelper.PageHelper;
+import com.github.pagehelper.PageInfo;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.List;
+
+@Api("商品信息")
+@RestController
+@RequestMapping(value="/saler/serviceGoods")
+public class FsServiceGoodsController {
+    @Autowired
+    private FsProductInfoService fsProductInfoService;
+
+    /**
+     * 分页查询商品列表
+     */
+    @ApiOperation("查看商品列表")
+    @PostMapping("/listPage")
+    public R listPage(@RequestBody ProductInfoListPageParam param) {
+        PageHelper.startPage(param.getPageNum(), param.getPageSize());
+        List<FsProductInfo> list = fsProductInfoService.getAll(param);
+        PageInfo<FsProductInfo> pageInfo = new PageInfo<>(list);
+        return R.ok().put("data", pageInfo);
+    }
+    /**
+     * 查看商品详情
+     */
+    @ApiOperation("查看商品详情")
+    @PostMapping("/findById")
+    public R findById(@RequestBody ProductInfoListPageParam param) {
+        FsProductInfo productInfo = fsProductInfoService.getById(param.getId());
+        return R.ok().put("data", productInfo);
+    }
+    /**
+     * 新增商品
+     */
+    @ApiOperation("新增商品")
+    @PostMapping("/save")
+    public R save(@RequestBody FsProductInfo productInfo) {
+        boolean result = fsProductInfoService.save(productInfo);
+        return result ? R.ok() : R.error("新增商品失败");
+    }
+    /**
+     * 更新商品信息
+     */
+    @ApiOperation("更新商品信息")
+    @PostMapping("/updateById")
+    public R updateById(@RequestBody FsProductInfo productInfo) {
+        boolean result = fsProductInfoService.update(productInfo);
+        return result ? R.ok() : R.error("更新商品信息失败");
+    }
+    /**
+     * 删除商品
+     */
+    @ApiOperation("删除商品")
+    @PostMapping("/deleteById")
+    public R deleteById(@RequestBody ProductInfoListPageParam param) {
+        boolean result = fsProductInfoService.removeById(param.getId());
+        return result ? R.ok() : R.error("删除商品失败");
+    }
+}

+ 30 - 0
fs-admin/src/main/java/com/fs/web/controller/system/SysConfigController.java

@@ -2,6 +2,9 @@ package com.fs.web.controller.system;
 
 import java.util.List;
 
+import cn.hutool.core.util.ObjectUtil;
+import com.fs.common.core.domain.R;
+import com.fs.common.core.redis.RedisCache;
 import com.fs.common.utils.SecurityUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
@@ -36,6 +39,8 @@ public class SysConfigController extends BaseController
 {
     @Autowired
     private ISysConfigService configService;
+    @Autowired
+    public RedisCache redisCache;
 
     /**
      * 获取参数配置列表
@@ -150,4 +155,29 @@ public class SysConfigController extends BaseController
         config.setCreateBy(SecurityUtils.getUsername());
         return toAjax(configService.updateConfig(config));
     }
+
+
+    /**
+     * 启用-关闭小程序销售管理
+     * @param bock
+     * @return
+     */
+    @GetMapping("/updateIsTownOn")
+    public R queryIsTownOn(String bock, String appId)
+    {
+        String key = appId+"start_status_001";
+        String start = redisCache.getCacheObject(key);
+        if (ObjectUtil.isNotEmpty(bock)){
+            if (bock.equals("001")){
+                redisCache.setCacheObject(key,bock);
+                return R.ok("调整成功");
+            }else if (bock.equals("002")){
+                redisCache.setCacheObject(key,bock);
+                return R.ok("调整成功");
+            }
+
+        }
+        return R.ok().put("date",start);
+    }
+
 }

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

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

+ 17 - 2
fs-common/src/main/java/com/fs/common/annotation/Log.java

@@ -7,10 +7,11 @@ import java.lang.annotation.RetentionPolicy;
 import java.lang.annotation.Target;
 import com.fs.common.enums.BusinessType;
 import com.fs.common.enums.OperatorType;
+import com.fs.common.utils.StringUtils;
 
 /**
  * 自定义操作日志记录注解
- * 
+ *
 
  *
  */
@@ -20,7 +21,7 @@ import com.fs.common.enums.OperatorType;
 public @interface Log
 {
     /**
-     * 模块 
+     * 模块
      */
     public String title() default "";
 
@@ -38,4 +39,18 @@ public @interface Log
      * 是否保存请求的参数
      */
     public boolean isSaveRequestData() default true;
+
+    /**
+     * 是否商城日志
+     */
+    public boolean isStoreLog() default false;
+
+    /**
+     * 商城日志传参
+     * */
+    public String[] logParam() default {};
+
+    String businessTypeExpression() default "";
+
+    String logParamExpression() default "";
 }

+ 3 - 0
fs-common/src/main/java/com/fs/common/core/redis/RedisCache.java

@@ -233,4 +233,7 @@ public class RedisCache
     }
 
 
+    public Boolean setIfAbsent(String key, String value, long timeout, TimeUnit unit) {
+        return redisTemplate.opsForValue().setIfAbsent(key, value, timeout, unit);
+    }
 }

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

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

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

@@ -271,4 +271,46 @@ public class DateUtils extends org.apache.commons.lang3.time.DateUtils
         return new SimpleDateFormat("yyyy-MM-dd").format(cal.getTime());
     }
 
+    /**
+     * @Description: yyyy-MM 获取当月的第一天
+     * @Param:
+     * @Return:
+     * @Author xgb
+     * @Date 2025/9/1 14:30
+     */
+    public static Date getStartOfMonth(Date date) {
+        Calendar calendar = Calendar.getInstance();
+        calendar.setTime(date);
+        calendar.set(Calendar.DAY_OF_MONTH, 1);
+        return calendar.getTime();
+    }
+
+    /**
+     * @Description: yyyy-MM 获取当月的最后一天
+     * @Param:
+     * @Return:
+     * @Author xgb
+     * @Date 2025/9/1 14:31
+     */
+
+    public static Date getEndOfMonth(Date date) {
+        Calendar calendar = Calendar.getInstance();
+        calendar.setTime(date);
+        calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
+        return calendar.getTime();
+    }
+
+    /**
+     * @Description: 根据日期获取星期 1-星期一 2-星期二 。。。6-星期六 0-星期日
+     * @Param:
+     * @Return:
+     * @Author xgb
+     * @Date 2025/9/5 14:04
+     */
+
+    public static int getWeek(Date date) {
+        Calendar calendar = Calendar.getInstance();
+        calendar.setTime(date);
+        return calendar.get(Calendar.DAY_OF_WEEK)-1;
+    }
 }

+ 3 - 0
fs-common/src/main/java/com/fs/common/utils/DictUtils.java

@@ -6,12 +6,14 @@ import com.fs.common.constant.Constants;
 import com.fs.common.core.domain.entity.SysDictData;
 import com.fs.common.core.redis.RedisCache;
 import com.fs.common.utils.spring.SpringUtils;
+import lombok.extern.slf4j.Slf4j;
 
 /**
  * 字典工具类
  *
 
  */
+@Slf4j
 public class DictUtils
 {
     /**
@@ -42,6 +44,7 @@ public class DictUtils
         if (StringUtils.isNotNull(cacheObj))
         {
             List<SysDictData> dictDatas = StringUtils.cast(cacheObj);
+            log.info("获取缓存 key: {} values: {}",key,dictDatas);
             return dictDatas;
         }
         return null;

+ 205 - 0
fs-common/src/main/java/com/fs/common/utils/FileNameExtractor.java

@@ -0,0 +1,205 @@
+package com.fs.common.utils;
+
+import org.apache.commons.io.FilenameUtils;
+import java.net.URL;
+import java.net.MalformedURLException;
+
+public class FileNameExtractor {
+
+    /**
+     * 使用Apache Commons IO获取文件名
+     * @param urlString URL字符串
+     * @return 文件名
+     */
+    public static String getFileNameFromUrl(String urlString) {
+        if (urlString == null || urlString.trim().isEmpty()) {
+            return null;
+        }
+
+        try {
+            URL url = new URL(urlString);
+            String path = url.getPath();
+            return FilenameUtils.getName(path);
+        } catch (MalformedURLException e) {
+            // 作为普通路径处理
+            return FilenameUtils.getName(urlString);
+        }
+    }
+
+    /**
+     * 获取不带扩展名的文件名
+     * @param urlString URL字符串
+     * @return 不带扩展名的文件名
+     */
+    public static String getBaseNameFromUrl(String urlString) {
+        if (urlString == null || urlString.trim().isEmpty()) {
+            return null;
+        }
+
+        try {
+            URL url = new URL(urlString);
+            String path = url.getPath();
+            return FilenameUtils.getBaseName(path);
+        } catch (MalformedURLException e) {
+            return FilenameUtils.getBaseName(urlString);
+        }
+    }
+
+    /**
+     * 获取文件扩展名
+     * @param urlString URL字符串
+     * @return 文件扩展名
+     */
+    public static String getExtensionFromUrl(String urlString) {
+        if (urlString == null || urlString.trim().isEmpty()) {
+            return null;
+        }
+
+        try {
+            URL url = new URL(urlString);
+            String path = url.getPath();
+            return FilenameUtils.getExtension(path);
+        } catch (MalformedURLException e) {
+            return FilenameUtils.getExtension(urlString);
+        }
+    }
+
+    /**
+     * 从URL或文件路径中获取扩展名
+     * @param urlOrPath URL字符串或文件路径
+     * @return 扩展名(不包含点号),如果没有扩展名则返回null
+     */
+    public static String getExtension(String urlOrPath) {
+        if (urlOrPath == null || urlOrPath.trim().isEmpty()) {
+            return null;
+        }
+
+        String fileName = getFileNameFromUrlOrPath(urlOrPath);
+        if (fileName == null || fileName.isEmpty()) {
+            return null;
+        }
+
+        // 查找最后一个点的位置
+        int lastDotIndex = fileName.lastIndexOf('.');
+
+        // 如果没有点,或者点在开头(隐藏文件),或者点在结尾,则没有扩展名
+        if (lastDotIndex <= 0 || lastDotIndex == fileName.length() - 1) {
+            return null;
+        }
+
+        return fileName.substring(lastDotIndex + 1).toLowerCase();
+    }
+
+    /**
+     * 从URL或文件路径中获取扩展名(包含点号)
+     * @param urlOrPath URL字符串或文件路径
+     * @return 扩展名(包含点号),如果没有扩展名则返回null
+     */
+    public static String getExtensionWithDot(String urlOrPath) {
+        String extension = getExtension(urlOrPath);
+        return extension != null ? "." + extension : null;
+    }
+
+    /**
+     * 检查文件是否具有指定的扩展名
+     * @param urlOrPath URL字符串或文件路径
+     * @param expectedExtension 期望的扩展名(可以带点号也可以不带)
+     * @return 是否匹配
+     */
+    public static boolean hasExtension(String urlOrPath, String expectedExtension) {
+        if (expectedExtension == null) {
+            return false;
+        }
+
+        String actualExtension = getExtension(urlOrPath);
+        if (actualExtension == null) {
+            return false;
+        }
+
+        // 处理期望扩展名可能带点号的情况
+        String cleanExpectedExtension = expectedExtension.startsWith(".") ?
+                expectedExtension.substring(1) : expectedExtension;
+
+        return actualExtension.equalsIgnoreCase(cleanExpectedExtension);
+    }
+
+    /**
+     * 检查文件是否是图片类型
+     * @param urlOrPath URL字符串或文件路径
+     * @return 是否是图片文件
+     */
+    public static boolean isImageFile(String urlOrPath) {
+        String extension = getExtension(urlOrPath);
+        if (extension == null) {
+            return false;
+        }
+
+        String[] imageExtensions = {"jpg", "jpeg", "png", "gif", "bmp", "webp", "svg", "ico"};
+        for (String imgExt : imageExtensions) {
+            if (extension.equalsIgnoreCase(imgExt)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * 检查文件是否是文档类型
+     * @param urlOrPath URL字符串或文件路径
+     * @return 是否是文档文件
+     */
+    public static boolean isDocumentFile(String urlOrPath) {
+        String extension = getExtension(urlOrPath);
+        if (extension == null) {
+            return false;
+        }
+
+        String[] docExtensions = {"pdf", "doc", "docx", "xls", "xlsx", "ppt", "pptx", "txt", "rtf"};
+        for (String docExt : docExtensions) {
+            if (extension.equalsIgnoreCase(docExt)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * 从URL或路径中提取文件名的辅助方法
+     */
+    private static String getFileNameFromUrlOrPath(String urlOrPath) {
+        try {
+            java.net.URL url = new java.net.URL(urlOrPath);
+            String path = url.getPath();
+
+            // 处理查询参数,移除?后面的内容
+            int queryIndex = path.indexOf('?');
+            if (queryIndex > 0) {
+                path = path.substring(0, queryIndex);
+            }
+
+            if (path.endsWith("/")) {
+                path = path.substring(0, path.length() - 1);
+            }
+
+            int lastSlashIndex = path.lastIndexOf('/');
+            return lastSlashIndex >= 0 ? path.substring(lastSlashIndex + 1) : path;
+
+        } catch (java.net.MalformedURLException e) {
+            // 作为普通路径处理
+            String path = urlOrPath.trim();
+
+            // 处理查询参数
+            int queryIndex = path.indexOf('?');
+            if (queryIndex > 0) {
+                path = path.substring(0, queryIndex);
+            }
+
+            if (path.endsWith("/") || path.endsWith("\\")) {
+                path = path.substring(0, path.length() - 1);
+            }
+
+            int lastSlashIndex = Math.max(path.lastIndexOf('/'), path.lastIndexOf('\\'));
+            return lastSlashIndex >= 0 ? path.substring(lastSlashIndex + 1) : path;
+        }
+    }
+}

Některé soubory nejsou zobrazeny, neboť je v těchto rozdílových datech změněno mnoho souborů