浏览代码

Merge remote-tracking branch 'origin/master'

ct 1 周之前
父节点
当前提交
02105318fd
共有 100 个文件被更改,包括 2115 次插入412 次删除
  1. 3 3
      fs-admin/src/main/java/com/fs/course/controller/FsCourseQuestionBankController.java
  2. 18 0
      fs-admin/src/main/java/com/fs/course/controller/FsUserWatchCourseStatisticsController.java
  3. 10 0
      fs-admin/src/main/java/com/fs/course/controller/FsUserWatchStatisticsController.java
  4. 21 14
      fs-admin/src/main/java/com/fs/crm/controller/CrmCustomerController.java
  5. 84 0
      fs-admin/src/main/java/com/fs/crm/controller/CrmCustomerLevelController.java
  6. 54 0
      fs-admin/src/main/java/com/fs/store/controller/FsStoreOrderStatisticsController.java
  7. 1 1
      fs-admin/src/main/java/com/fs/store/controller/FsUserController.java
  8. 28 0
      fs-admin/src/main/java/com/fs/store/vo/StoreOrderStatisticsVo.java
  9. 19 0
      fs-admin/src/main/java/com/fs/task/OrderTask.java
  10. 1 1
      fs-admin/src/main/resources/application.yml
  11. 23 2
      fs-admin/src/test/java/com/fs/course/controller/FsCourseDomainNameControllerTest.java
  12. 12 7
      fs-company-app/src/main/java/com/fs/app/controller/FsUserController.java
  13. 16 2
      fs-company-app/src/main/java/com/fs/app/controller/FsUserCourseVideoController.java
  14. 110 4
      fs-company-app/src/main/java/com/fs/app/controller/VoiceApiController.java
  15. 0 137
      fs-company-app/src/main/resources/application-druid-fby.yml
  16. 1 2
      fs-company-app/src/main/resources/application.yml
  17. 35 0
      fs-company/src/main/java/com/fs/company/controller/CompanyRechargeController.java
  18. 16 0
      fs-company/src/main/java/com/fs/company/controller/CompanyUserController.java
  19. 18 0
      fs-company/src/main/java/com/fs/course/controller/FsUserWatchCourseStatisticsController.java
  20. 29 3
      fs-company/src/main/java/com/fs/crm/controller/CrmCustomerController.java
  21. 40 0
      fs-company/src/main/java/com/fs/crm/controller/CrmCustomerLevelController.java
  22. 20 28
      fs-company/src/main/java/com/fs/pay/controller/WxPayController.java
  23. 1 1
      fs-company/src/main/java/com/fs/users/controller/FsUserController.java
  24. 1 1
      fs-company/src/main/resources/application.yml
  25. 1 1
      fs-qw-task/src/main/resources/application.yml
  26. 83 0
      fs-service-system/src/main/java/com/fs/company/constant/PaymentStatus.java
  27. 75 0
      fs-service-system/src/main/java/com/fs/company/domain/CompanyRechargeOrder.java
  28. 22 0
      fs-service-system/src/main/java/com/fs/company/domain/CompanyUser.java
  29. 15 0
      fs-service-system/src/main/java/com/fs/company/dto/RechargeDTO.java
  30. 3 0
      fs-service-system/src/main/java/com/fs/company/mapper/CompanyMapper.java
  31. 74 0
      fs-service-system/src/main/java/com/fs/company/mapper/CompanyRechargeOrderMapper.java
  32. 7 0
      fs-service-system/src/main/java/com/fs/company/mapper/CompanyUserMapper.java
  33. 16 0
      fs-service-system/src/main/java/com/fs/company/service/CompanyRechargeOrderService.java
  34. 17 0
      fs-service-system/src/main/java/com/fs/company/service/ICompanyRechargeService.java
  35. 10 0
      fs-service-system/src/main/java/com/fs/company/service/ICompanyUserService.java
  36. 2 0
      fs-service-system/src/main/java/com/fs/company/service/ICompanyVoiceCallerService.java
  37. 101 0
      fs-service-system/src/main/java/com/fs/company/service/impl/CompanyRechargeOrderServiceImpl.java
  38. 61 2
      fs-service-system/src/main/java/com/fs/company/service/impl/CompanyRechargeServiceImpl.java
  39. 7 1
      fs-service-system/src/main/java/com/fs/company/service/impl/CompanyTagUserServiceImpl.java
  40. 19 2
      fs-service-system/src/main/java/com/fs/company/service/impl/CompanyUserServiceImpl.java
  41. 6 0
      fs-service-system/src/main/java/com/fs/company/service/impl/CompanyVoiceCallerServiceImpl.java
  42. 4 0
      fs-service-system/src/main/java/com/fs/company/vo/CompanyUserQwListVO.java
  43. 3 0
      fs-service-system/src/main/java/com/fs/config/cloud/CloudHostProper.java
  44. 10 2
      fs-service-system/src/main/java/com/fs/course/domain/FsUserWatchCourseStatistics.java
  45. 4 1
      fs-service-system/src/main/java/com/fs/course/domain/FsUserWatchStatistics.java
  46. 1 1
      fs-service-system/src/main/java/com/fs/course/mapper/FsUserCourseCategoryMapper.java
  47. 2 1
      fs-service-system/src/main/java/com/fs/course/service/IFsCourseQuestionBankService.java
  48. 6 2
      fs-service-system/src/main/java/com/fs/course/service/impl/FsCourseLinkServiceImpl.java
  49. 7 4
      fs-service-system/src/main/java/com/fs/course/service/impl/FsCourseQuestionBankServiceImpl.java
  50. 24 9
      fs-service-system/src/main/java/com/fs/course/service/impl/FsUserCourseServiceImpl.java
  51. 5 0
      fs-service-system/src/main/java/com/fs/course/service/impl/FsUserCourseVideoServiceImpl.java
  52. 67 26
      fs-service-system/src/main/java/com/fs/course/service/impl/FsUserWatchStatisticsServiceImpl.java
  53. 5 1
      fs-service-system/src/main/java/com/fs/course/vo/FsUserWatchCourseStatisticsExportVO.java
  54. 10 6
      fs-service-system/src/main/java/com/fs/crm/domain/CrmCustomer.java
  55. 28 0
      fs-service-system/src/main/java/com/fs/crm/domain/CrmCustomerLevel.java
  56. 18 0
      fs-service-system/src/main/java/com/fs/crm/mapper/CrmCustomerLevelMapper.java
  57. 17 5
      fs-service-system/src/main/java/com/fs/crm/mapper/CrmCustomerMapper.java
  58. 26 0
      fs-service-system/src/main/java/com/fs/crm/param/CrmCustomerLevelParm.java
  59. 11 0
      fs-service-system/src/main/java/com/fs/crm/param/CrmCustomerLevelQueryParam.java
  60. 4 1
      fs-service-system/src/main/java/com/fs/crm/param/CrmCustomerListQueryParam.java
  61. 3 0
      fs-service-system/src/main/java/com/fs/crm/param/CrmFullCustomerListQueryParam.java
  62. 2 0
      fs-service-system/src/main/java/com/fs/crm/param/CrmLineCustomerListQueryParam.java
  63. 3 0
      fs-service-system/src/main/java/com/fs/crm/param/CrmMyCustomerListQueryParam.java
  64. 3 0
      fs-service-system/src/main/java/com/fs/crm/service/ICrmCustomerAssistService.java
  65. 40 0
      fs-service-system/src/main/java/com/fs/crm/service/ICrmCustomerLevelService.java
  66. 12 5
      fs-service-system/src/main/java/com/fs/crm/service/ICrmCustomerService.java
  67. 9 8
      fs-service-system/src/main/java/com/fs/crm/service/impl/CrmCustomerAssistServiceImpl.java
  68. 102 0
      fs-service-system/src/main/java/com/fs/crm/service/impl/CrmCustomerLevelServiceImpl.java
  69. 72 0
      fs-service-system/src/main/java/com/fs/crm/service/impl/CrmCustomerServiceImpl.java
  70. 23 0
      fs-service-system/src/main/java/com/fs/crm/vo/CrmCustomerLevelVO.java
  71. 5 0
      fs-service-system/src/main/java/com/fs/crm/vo/CrmCustomerListVO.java
  72. 3 0
      fs-service-system/src/main/java/com/fs/crm/vo/CrmFullCustomerListQueryVO.java
  73. 4 0
      fs-service-system/src/main/java/com/fs/crm/vo/CrmLineCustomerListQueryVO.java
  74. 3 0
      fs-service-system/src/main/java/com/fs/crm/vo/CrmMyCustomerListQueryVO.java
  75. 5 1
      fs-service-system/src/main/java/com/fs/statis/service/impl/StatisticsCompanyServiceImpl.java
  76. 10 5
      fs-service-system/src/main/java/com/fs/store/mapper/FsStoreOrderMapper.java
  77. 11 9
      fs-service-system/src/main/java/com/fs/store/mapper/FsUserMapper.java
  78. 5 0
      fs-service-system/src/main/java/com/fs/store/param/FsStoreOrderParam.java
  79. 26 0
      fs-service-system/src/main/java/com/fs/store/param/FsStoreOrderStatisticsParam.java
  80. 15 0
      fs-service-system/src/main/java/com/fs/store/service/IFsStoreOrderService.java
  81. 10 0
      fs-service-system/src/main/java/com/fs/store/service/impl/FsStoreOrderServiceImpl.java
  82. 63 9
      fs-service-system/src/main/java/com/fs/store/service/impl/FsUserServiceImpl.java
  83. 8 0
      fs-service-system/src/main/java/com/fs/wx/pay/config/WxPayProperties.java
  84. 5 0
      fs-service-system/src/main/resources/application-config-bly.yml
  85. 2 0
      fs-service-system/src/main/resources/application-config-dev.yml
  86. 10 5
      fs-service-system/src/main/resources/application-config-fby.yml
  87. 2 0
      fs-service-system/src/main/resources/application-config-zkzh.yml
  88. 2 0
      fs-service-system/src/main/resources/application-dev.yml
  89. 2 0
      fs-service-system/src/main/resources/application-druid-bly.yml
  90. 2 0
      fs-service-system/src/main/resources/application-druid-fby.yml
  91. 14 0
      fs-service-system/src/main/resources/db/upgrade/20250621客户分级.sql
  92. 8 0
      fs-service-system/src/main/resources/mapper/company/CompanyMapper.xml
  93. 10 1
      fs-service-system/src/main/resources/mapper/company/CompanyUserMapper.xml
  94. 15 7
      fs-service-system/src/main/resources/mapper/course/FsUserCourseMapper.xml
  95. 7 13
      fs-service-system/src/main/resources/mapper/course/FsUserWatchStatisticsMapper.xml
  96. 17 0
      fs-service-system/src/main/resources/mapper/crm/CrmCustomerLevelMapper.xml
  97. 20 3
      fs-service-system/src/main/resources/mapper/crm/CrmCustomerMapper.xml
  98. 6 10
      fs-service-system/src/main/resources/mapper/statis/ConsumptionBalanceMapper.xml
  99. 23 0
      fs-service-system/src/main/resources/mapper/store/FsStoreOrderMapper.xml
  100. 201 65
      fs-service-system/src/main/resources/mapper/store/FsUserMapper.xml

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

@@ -58,14 +58,15 @@ public class FsCourseQuestionBankController extends BaseController
     @GetMapping("/export")
     public AjaxResult export(FsCourseQuestionBank fsCourseQuestionBank)
     {
+        List<FsCourseQuestionBankImportDTO> list = fsCourseQuestionBankService.exportData(fsCourseQuestionBank);
         LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
         Long userId = loginUser.getUser().getUserId();
         fsCourseQuestionBank.setUserId(userId);
-        List<FsCourseQuestionBankImportDTO> list = fsCourseQuestionBankService.exportData(fsCourseQuestionBank);
         ExcelUtil<FsCourseQuestionBankImportDTO> util = new ExcelUtil<>(FsCourseQuestionBankImportDTO.class);
         return util.exportExcel(list, "题库数据");
     }
 
+
     /**
      * 获取题库详细信息
      */
@@ -126,9 +127,8 @@ public class FsCourseQuestionBankController extends BaseController
     public AjaxResult importData(MultipartFile file) throws Exception {
         ExcelUtil<FsCourseQuestionBankImportDTO> util = new ExcelUtil<>(FsCourseQuestionBankImportDTO.class);
         List<FsCourseQuestionBankImportDTO> list = util.importExcel(file.getInputStream());
-
         LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
-        String message = fsCourseQuestionBankService.importData(list, loginUser.getUser().getNickName(), loginUser.getUser().getUserId());
+        String message = fsCourseQuestionBankService.importData(list, loginUser.getUser().getNickName(),loginUser.getUser().getUserId());
         return AjaxResult.success(message);
     }
 

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

@@ -46,6 +46,12 @@ public class FsUserWatchCourseStatisticsController extends BaseController
     {
         startPage();
         List<FsUserWatchCourseStatistics> list = fsUserWatchCourseStatisticsService.selectFsUserWatchCourseStatisticsList(fsUserWatchCourseStatistics);
+        if(!list.isEmpty()){
+            for (FsUserWatchCourseStatistics userWatchCourseStatistics : list) {
+                userWatchCourseStatistics.setCompleteWatchRatePercent(userWatchCourseStatistics.getCompleteWatchRate() + "%");
+                userWatchCourseStatistics.setAnswerRightRatePercent(userWatchCourseStatistics.getAnswerRightRate() + "%");
+            }
+        }
         return getDataTable(list);
     }
 
@@ -58,6 +64,12 @@ public class FsUserWatchCourseStatisticsController extends BaseController
     public AjaxResult export(FsUserWatchCourseStatistics fsUserWatchCourseStatistics)
     {
         List<FsUserWatchCourseStatistics> list = fsUserWatchCourseStatisticsService.selectFsUserWatchCourseStatisticsList(fsUserWatchCourseStatistics);
+        if(!list.isEmpty()){
+            for (FsUserWatchCourseStatistics userWatchCourseStatistics : list) {
+                userWatchCourseStatistics.setCompleteWatchRatePercent(userWatchCourseStatistics.getCompleteWatchRate() + "%");
+                userWatchCourseStatistics.setAnswerRightRatePercent(userWatchCourseStatistics.getAnswerRightRate() + "%");
+            }
+        }
         ExcelUtil<FsUserWatchCourseStatistics> util = new ExcelUtil<FsUserWatchCourseStatistics>(FsUserWatchCourseStatistics.class);
         return util.exportExcel(list, "会员观看数据明细");
     }
@@ -114,6 +126,11 @@ public class FsUserWatchCourseStatisticsController extends BaseController
     {
         startPage();
         List<FsUserWatchCourseStatistics> list = fsUserWatchCourseStatisticsService.selectFsUserWatchCourseStatisticsListTotal(fsUserWatchCourseStatistics);
+        if(!list.isEmpty()){
+            for (FsUserWatchCourseStatistics userWatchCourseStatistics : list) {
+                userWatchCourseStatistics.setCompleteWatchRatePercent(userWatchCourseStatistics.getCompleteWatchRate() + "%");
+            }
+        }
         return getDataTable(list);
     }
 
@@ -128,6 +145,7 @@ public class FsUserWatchCourseStatisticsController extends BaseController
         List<FsUserWatchCourseStatisticsExportVO> listVO = list.stream().map(v -> {
             FsUserWatchCourseStatisticsExportVO vo = new FsUserWatchCourseStatisticsExportVO();
             BeanUtils.copyProperties(v, vo);
+            vo.setCompleteWatchRatePercent(v.getCompleteWatchRate() + "%");
             return vo;
         }).collect(Collectors.toList());
         ExcelUtil<FsUserWatchCourseStatisticsExportVO> util = new ExcelUtil<FsUserWatchCourseStatisticsExportVO>(FsUserWatchCourseStatisticsExportVO.class);

+ 10 - 0
fs-admin/src/main/java/com/fs/course/controller/FsUserWatchStatisticsController.java

@@ -44,6 +44,11 @@ public class FsUserWatchStatisticsController extends BaseController
     {
         startPage();
         List<FsUserWatchStatistics> list = fsUserWatchStatisticsService.selectFsUserWatchStatisticsList(fsUserWatchStatistics);
+        if(!list.isEmpty()){
+            for (FsUserWatchStatistics userWatchStatistics : list) {
+                userWatchStatistics.setCompleteWatchRatePercent(userWatchStatistics.getCompleteWatchRate() + "%");
+            }
+        }
         return getDataTable(list);
     }
 
@@ -56,6 +61,11 @@ public class FsUserWatchStatisticsController extends BaseController
     public AjaxResult export(FsUserWatchStatistics fsUserWatchStatistics)
     {
         List<FsUserWatchStatistics> list = fsUserWatchStatisticsService.selectFsUserWatchStatisticsList(fsUserWatchStatistics);
+        if(!list.isEmpty()){
+            for (FsUserWatchStatistics userWatchStatistics : list) {
+                userWatchStatistics.setCompleteWatchRatePercent(userWatchStatistics.getCompleteWatchRate() + "%");
+            }
+        }
         ExcelUtil<FsUserWatchStatistics> util = new ExcelUtil<FsUserWatchStatistics>(FsUserWatchStatistics.class);
         return util.exportExcel(list, "会员看课统计-按营期统计数据");
     }

+ 21 - 14
fs-admin/src/main/java/com/fs/crm/controller/CrmCustomerController.java

@@ -1,35 +1,35 @@
 package com.fs.crm.controller;
 
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
+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.OrderUtils;
 import com.fs.common.utils.ServletUtils;
 import com.fs.common.utils.StringUtils;
+import com.fs.common.utils.poi.ExcelUtil;
 import com.fs.company.domain.Company;
 import com.fs.company.service.ICompanyService;
 import com.fs.core.security.LoginUser;
 import com.fs.core.web.service.TokenService;
+import com.fs.crm.domain.CrmCustomer;
 import com.fs.crm.param.*;
-import com.fs.crm.vo.CrmCustomerListVO;
+import com.fs.crm.service.ICrmCustomerService;
 import com.fs.crm.vo.CrmCustomerExportVO;
-import com.fs.store.vo.FsStoreOrderVO;
+import com.fs.crm.vo.CrmCustomerListVO;
+import io.swagger.annotations.ApiOperation;
 import org.springframework.beans.BeanUtils;
-import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
-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.crm.domain.CrmCustomer;
-import com.fs.crm.service.ICrmCustomerService;
-import com.fs.common.utils.poi.ExcelUtil;
-import com.fs.common.core.page.TableDataInfo;
 import org.springframework.web.multipart.MultipartFile;
 
+import java.util.ArrayList;
+import java.util.List;
+
 /**
  * 客户Controller
  *
@@ -282,5 +282,12 @@ public class CrmCustomerController extends BaseController
         return R.ok().put("data",customerList);
     }
 
+    @ApiOperation("置顶切换")
+    @PreAuthorize("@ss.hasPermi('crm:customer:switchToTop')")
+    @PostMapping("/switchToTop/{customerId}")
+    public R switchToTop(@PathVariable Long customerId) {
+        crmCustomerService.switchToTop(customerId);
+        return R.ok();
+    }
 
 }

+ 84 - 0
fs-admin/src/main/java/com/fs/crm/controller/CrmCustomerLevelController.java

@@ -0,0 +1,84 @@
+package com.fs.crm.controller;
+
+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.domain.R;
+import com.fs.common.core.page.TableDataInfo;
+import com.fs.common.enums.BusinessType;
+import com.fs.crm.domain.CrmCustomerLevel;
+import com.fs.crm.param.CrmCustomerLevelParm;
+import com.fs.crm.param.CrmCustomerLevelQueryParam;
+import com.fs.crm.service.ICrmCustomerLevelService;
+import com.fs.crm.vo.CrmCustomerLevelVO;
+import com.fs.his.vo.OptionsVO;
+import lombok.AllArgsConstructor;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import javax.validation.Valid;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Objects;
+import java.util.stream.Collectors;
+
+@RestController
+@RequestMapping("/crm/customerLevel")
+@AllArgsConstructor
+public class CrmCustomerLevelController extends BaseController {
+
+    private final ICrmCustomerLevelService customerLevelService;
+
+    @PreAuthorize("@ss.hasPermi('crm:customerLevel:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(CrmCustomerLevelQueryParam param) {
+        startPage();
+        List<CrmCustomerLevelVO> list = customerLevelService.selectCrmCustomerLevelVOList(param);
+        return getDataTable(list);
+    }
+
+    @PreAuthorize("@ss.hasPermi('crm:customerLevel:add')")
+    @Log(title = "客户级别", businessType = BusinessType.INSERT)
+    @PostMapping("/add")
+    public AjaxResult add(@Valid @RequestBody CrmCustomerLevelParm param) {
+        return toAjax(customerLevelService.saveCustomerLevel(param));
+    }
+
+    @PreAuthorize("@ss.hasPermi('crm:customerLevel:edit')")
+    @Log(title = "客户级别", businessType = BusinessType.UPDATE)
+    @PutMapping("/edit")
+    public AjaxResult edit(@Valid @RequestBody CrmCustomerLevelParm param) {
+        return toAjax(customerLevelService.editCustomerLevel(param));
+    }
+
+    @PreAuthorize("@ss.hasPermi('crm:customerLevel:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable Long id) {
+        return AjaxResult.success(customerLevelService.selectCrmCustomerLevelVOById(id));
+    }
+
+    @PreAuthorize("@ss.hasPermi('crm:customerLevel:delete')")
+    @Log(title = "客户", businessType = BusinessType.DELETE)
+    @DeleteMapping("/delete/{ids}")
+    public AjaxResult delete(@PathVariable Long[] ids) {
+        customerLevelService.removeByIds(Arrays.asList(ids));
+        return AjaxResult.success();
+    }
+
+    @GetMapping("/getCustomerLevelOption")
+    public R getCustomerLevelOption(Integer status) {
+        LambdaQueryWrapper<CrmCustomerLevel> wrapper = Wrappers.lambdaQuery();
+        if (Objects.nonNull(status)) {
+            wrapper.eq(CrmCustomerLevel::getStatus, status);
+        }
+        List<OptionsVO> options = customerLevelService.list(wrapper).stream().map(l -> {
+            OptionsVO vo = new OptionsVO();
+            vo.setDictLabel(l.getName());
+            vo.setDictValue(l.getId());
+            return vo;
+        }).collect(Collectors.toList());
+        return R.ok().put("data", options);
+    }
+}

+ 54 - 0
fs-admin/src/main/java/com/fs/store/controller/FsStoreOrderStatisticsController.java

@@ -0,0 +1,54 @@
+package com.fs.store.controller;
+
+import com.baomidou.mybatisplus.extension.api.R;
+import com.fs.store.param.FsStoreOrderStatisticsParam;
+import com.fs.store.service.IFsStoreOrderService;
+import com.fs.store.vo.StoreOrderStatisticsVo;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.math.BigDecimal;
+
+
+@RestController
+@RequestMapping("/store/storeOrder/statistics")
+public class FsStoreOrderStatisticsController {
+
+    @Autowired
+    private IFsStoreOrderService storeOrderService;
+
+    @ApiOperation("订单统计")
+    @GetMapping("/getStoreOrderStatistics")
+    public R getStoreOrderStatistics(FsStoreOrderStatisticsParam param)
+    {
+        Integer orderCount = storeOrderService.selectFsStoreOrderCount(param);
+        param.setPaid(1);
+        //实际支付金额
+        BigDecimal totalAmount = storeOrderService.selectFsStoreOrderByPayPriceCount(param);
+        //已支付的总订单数
+        Integer orderPayCount = storeOrderService.selectFsStoreOrderCount(param);
+        //已完成订单
+        param.setStatus(5);
+        Integer orderCompleteCount = storeOrderService.selectFsStoreOrderCount(param);
+        //退货成功订单
+        param.setStatus(-2);
+        Integer orderReturnCount = storeOrderService.selectFsStoreOrderCount(param);
+        //成交率
+        int successRate = 0;
+        //退货率
+        int returnRate = 0;
+        if (orderPayCount != null && orderPayCount != 0) {
+            successRate = (int) Math.round((orderCompleteCount != null ? orderCompleteCount : 0) * 100.0 / orderPayCount);
+            returnRate = (int) Math.round((orderReturnCount != null ? orderReturnCount : 0) * 100.0 / orderPayCount);
+        }
+        StoreOrderStatisticsVo storeOrderStatisticsVo = new StoreOrderStatisticsVo();
+        storeOrderStatisticsVo.setOrderCount(orderCount);
+        storeOrderStatisticsVo.setTotalAmount(totalAmount);
+        storeOrderStatisticsVo.setSuccessRate(successRate);
+        storeOrderStatisticsVo.setReturnRate(returnRate);
+        return R.ok(storeOrderStatisticsVo);
+    }
+}

+ 1 - 1
fs-admin/src/main/java/com/fs/store/controller/FsUserController.java

@@ -160,7 +160,7 @@ public class FsUserController extends BaseController
     @ApiOperation("小黑屋")
     public R darkRoomList(FsUserPageListParam param) {
 //        startPage();
-        PageHelper.startPage(param.getPageNum(), param.getPageSize());
+//        PageHelper.startPage(param.getPageNum(), param.getPageSize());
         PageInfo<FsUserPageListVO> fsUserPageListVOPageInfo = fsUserService.selectFsUserPageList(param);
         for (FsUserPageListVO fsUserPageListVO : fsUserPageListVOPageInfo.getList()) {
             fsUserPageListVO.setPhone(ParseUtils.parsePhone(fsUserPageListVO.getPhone()));

+ 28 - 0
fs-admin/src/main/java/com/fs/store/vo/StoreOrderStatisticsVo.java

@@ -0,0 +1,28 @@
+package com.fs.store.vo;
+
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+@Data
+public class StoreOrderStatisticsVo {
+    /**
+     * 订单总量
+     */
+    Integer orderCount;
+
+    /**
+     * 总金额
+     */
+    BigDecimal totalAmount;
+
+    /**
+     * 成交率
+     */
+    Integer successRate;
+
+    /**
+     * 退货率
+     */
+    Integer returnRate;
+}

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

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

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

@@ -6,6 +6,6 @@ server:
 spring:
   profiles:
     active: dev
-    include: common,config-dev
+#    include: common,config-bly
 #    active: druid-fby
 #    include: common,config-fby

+ 23 - 2
fs-admin/src/test/java/com/fs/course/controller/FsCourseDomainNameControllerTest.java

@@ -5,6 +5,7 @@ import cn.hutool.json.JSONUtil;
 import com.fs.FSAdminApplication;
 import com.fs.course.config.RedPacketConfig;
 import com.fs.system.service.ISysConfigService;
+import com.github.binarywang.wxpay.bean.request.WxPayRefundRequest;
 import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
 import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderV3Request;
 import com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderResult;
@@ -38,8 +39,6 @@ class FsCourseDomainNameControllerTest {
     private ISysConfigService configService;
     @Test
     public void nativePay() throws WxPayException {
-        String json = configService.selectConfigByKey("redPacket.config");
-        RedPacketConfig config = JSONUtil.toBean(json, RedPacketConfig.class);
 
         WxPayConfig payConfig = new WxPayConfig();
         payConfig.setAppId("wx961fadab9bcb792b");
@@ -77,4 +76,26 @@ class FsCourseDomainNameControllerTest {
         log.info("请求结果: {}",order);
     }
 
+    @Test
+    public void refund() throws WxPayException {
+        WxPayConfig payConfig = new WxPayConfig();
+        payConfig.setAppId("wx961fadab9bcb792b");
+        payConfig.setMchId("1716217886");
+        payConfig.setMchKey("a7Fc5B9dE2h8J3kL4mN6pQ7rS9tU2vW1");
+        payConfig.setPrivateKeyPath("C:\\cert\\1716217886_20250509_cert\\apiclient_key.pem");
+        payConfig.setPrivateCertPath("C:\\cert\\1716217886_20250509_cert\\apiclient_cert.pem");
+        payConfig.setKeyPath("C:\\cert\\1716217886_20250509_cert\\apiclient_cert.p12");
+        payConfig.setCertSerialNo("4E8BD68BC2BFD37CA58244D660E5FDCCE475D82E");
+        payConfig.setUseSandboxEnv(false);
+        payConfig.setSignType(WxPayConstants.SignType.HMAC_SHA256);
+
+        wxPayService.setConfig(payConfig);
+        WxPayRefundRequest wxPayRefundRequest = new WxPayRefundRequest();
+        wxPayRefundRequest.setTransactionId("4200002745202506242171692915");
+        wxPayRefundRequest.setRefundFee(1);
+        wxPayRefundRequest.setTotalFee(1);
+        wxPayRefundRequest.setOutRefundNo("202506241450250001");
+        wxPayService.refund(wxPayRefundRequest);
+    }
+
 }

+ 12 - 7
fs-company-app/src/main/java/com/fs/app/controller/FsUserController.java

@@ -42,11 +42,11 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
 
 import javax.validation.Valid;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
 import java.io.InputStream;
-import java.text.SimpleDateFormat;
+import java.text.ParseException;
 import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
 import java.util.*;
 
 @Slf4j
@@ -81,7 +81,7 @@ public class FsUserController extends AppBaseController {
     @ApiOperation("用户会员分页列表")
     public ResponseResult<PageInfo<FsUserPageListVO>> pageList(@RequestBody FsUserPageListParam param) {
         param.setUserId(Long.parseLong(getUserId()));
-        PageHelper.startPage(param.getPageNum(), param.getPageSize());
+//        PageHelper.startPage(param.getPageNum(), param.getPageSize());
         PageInfo<FsUserPageListVO> fsUserPageListVOPageInfo = fsUserService.selectFsUserPageList(param);
 //        PageInfo<FsUserPageListVO> pageInfo = new PageInfo<>(list);
         return ResponseResult.ok(fsUserPageListVOPageInfo);
@@ -159,18 +159,23 @@ public class FsUserController extends AppBaseController {
     public ResponseResult<FsUserStatisticsVO> userStatistics(@ApiParam(value = "开始时间", required = true) @RequestParam String startTime,
                                                              @ApiParam(value = "结束时间", required = true) @RequestParam String endTime) {
         long userId = Long.parseLong(getUserId());
-        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
-        String nowDate = dateFormat.format(new Date());
         /*---------- 如果传入的日期是今天 ----------*/
         UserStatisticsCommonParam param = new UserStatisticsCommonParam();
         param.setUserId(userId).setStartTime(startTime).setEndTime(endTime);
         FsUserStatisticsVO vo = fsUserService.userStatistics(param);
-        if (nowDate.compareTo(startTime) > 0 && nowDate.compareTo(endTime) < 0) {
+
+        DateTimeFormatter dfm = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
+        LocalDate today = LocalDate.now();
+        LocalDateTime startDateTime = LocalDateTime.parse(startTime, dfm);
+        LocalDateTime endDateTime = LocalDateTime.parse(endTime, dfm);
+        if (startDateTime.toLocalDate().equals(today) && endDateTime.toLocalDate().equals(today)) {
             String yesterday = LocalDate.now().minusDays(1).toString();
             UserStatisticsCommonParam paramYes = new UserStatisticsCommonParam();
             paramYes.setUserId(userId).setStartTime(yesterday + " 00:00:00").setEndTime(yesterday + " 23:59:59");
             FsUserStatisticsVO fsUserStatisticsVO = fsUserService.userStatistics(paramYes);
             vo.setYesterdayVO(fsUserStatisticsVO);
+        } else {
+            vo.setYesterdayVO(new FsUserStatisticsVO());
         }
         return ResponseResult.ok(vo);
     }

+ 16 - 2
fs-company-app/src/main/java/com/fs/app/controller/FsUserCourseVideoController.java

@@ -5,6 +5,8 @@ import com.fs.app.config.ImageStorageConfig;
 import com.fs.common.core.domain.R;
 import com.fs.common.core.domain.ResponseResult;
 import com.fs.common.utils.StringUtils;
+import com.fs.company.domain.CompanyUser;
+import com.fs.company.service.ICompanyUserService;
 import com.fs.course.domain.FsUserCoursePeriod;
 import com.fs.course.param.FsCourseLinkCreateParam;
 import com.fs.course.param.newfs.FsCourseSortLinkParam;
@@ -30,7 +32,6 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
 
 import java.io.InputStream;
-import java.time.LocalDate;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -58,6 +59,8 @@ public class FsUserCourseVideoController extends AppBaseController {
 
     @Autowired
     private IFsUserCoursePeriodService fsUserCoursePeriodService;
+    @Autowired
+    private ICompanyUserService companyUserService;
 
     @Login
     @GetMapping("/pageList")
@@ -108,12 +111,23 @@ public class FsUserCourseVideoController extends AppBaseController {
                                                       @RequestParam(required = false) String keyword,
                                                       @RequestParam(required = false, defaultValue = "1") Integer pageNum,
                                                       @RequestParam(required = false, defaultValue = "10") Integer pageSize) {
-        log.debug("参与记录 keyword: {}, pageNum: {}, pageSize: {}", keyword, pageNum, pageSize);
+        log.debug("参与记录 videoId:{}, type:{}, keyword: {}, pageNum: {}, pageSize: {}", videoId, type, keyword, pageNum, pageSize);
         Map<String, Object> params = new HashMap<>();
         params.put("videoId", videoId);
         params.put("type", type);
         params.put("keyword", keyword);
 
+        // type 0 答题领奖记录----答题正确并且领取红包的
+        // type 1 完播----这堂课看完的人
+        // type 2 未完播---看课中断
+        // 管理员看整个公司 否则看自己的
+        CompanyUser companyUser = companyUserService.selectCompanyUserByUserId(Long.parseLong(getUserId()));
+        if (companyUser.isAdmin()) {
+            params.put("companyId", companyUser.getCompanyId());
+        } else {
+            params.put("companyUserId", companyUser.getUserId());
+        }
+
         PageHelper.startPage(pageNum, pageSize);
         List<FsUserCourseParticipationRecordVO> record = fsUserCourseService.getParticipationRecordByMap(params);
         return ResponseResult.ok(new PageInfo<>(record));

+ 110 - 4
fs-company-app/src/main/java/com/fs/app/controller/VoiceApiController.java

@@ -15,11 +15,12 @@ import com.fs.common.core.controller.BaseController;
 import com.fs.common.core.domain.R;
 import com.fs.common.utils.ServletUtils;
 import com.fs.common.utils.StringUtils;
-import com.fs.company.domain.CompanyUser;
-import com.fs.company.domain.CompanyVoiceApi;
-import com.fs.company.domain.CompanyVoiceLogs;
-import com.fs.company.domain.CompanyVoiceMobile;
+import com.fs.company.domain.*;
 import com.fs.company.service.*;
+import com.fs.crm.domain.CrmCustomer;
+import com.fs.crm.domain.CrmCustomerContacts;
+import com.fs.crm.service.ICrmCustomerContactsService;
+import com.fs.crm.service.ICrmCustomerService;
 import com.fs.system.oss.CloudStorageService;
 import com.fs.system.oss.OSSFactory;
 import com.fs.voice.service.IVoiceService;
@@ -72,6 +73,28 @@ public class VoiceApiController extends AppBaseController {
     private ICompanyVoiceService companyVoiceService;
     @Autowired
     private ICompanyVoiceMobileService companyVoiceMobileService;
+
+    @Autowired
+    private ICompanyVoiceCallerService callerService;
+
+    @Autowired
+    private ICompanyService companyService;
+
+    @Autowired
+    private ICompanyUserService userService;
+
+    @Autowired
+    private ICrmCustomerService crmService;
+
+    @Autowired
+    private ICrmCustomerContactsService crmContactsService;
+
+    @Autowired
+    private ICompanyVoiceBlacklistService blacklistService;
+
+    @Autowired
+    ICompanyVoiceLogsService logsService;
+
     @Autowired
     JwtUtils jwtUtils;
     @Login
@@ -154,6 +177,31 @@ public class VoiceApiController extends AppBaseController {
                 logs.setStatus(-1);
                 companyVoiceLogsService.updateCompanyVoiceLogs(logs);
             }
+        }else{
+            JSONObject callObj=JSON.parseObject(json);
+            JSONObject notifyObj=callObj.getJSONObject("notify");
+            String type=notifyObj.getString("type");
+            String session=notifyObj.getString("session");
+            String callee=notifyObj.getString("agent");//被叫/坐席号
+            String caller=notifyObj.getString("number");//主叫
+            if(type.contentEquals("callin")){   //回拨接听
+                CompanyVoiceCaller callerEE=callerService.selectCompanyVoiceCallerByCallerNo(callee);
+                CrmCustomer customer=crmService.selectFscrmByMobile(caller);
+                Long customerId=0L;
+                if(customer!=null){
+                    customerId=customer.getCustomerId();
+                }
+                else{
+                    CrmCustomerContacts contactsMap=new CrmCustomerContacts();
+                    contactsMap.setMobile(caller);
+                    List<CrmCustomerContacts>  contactsList=crmContactsService.selectCrmCustomerContactsList(contactsMap);
+                    if(contactsList.size()>0){
+                        CrmCustomerContacts contacts=contactsList.get(0);
+                        customerId=contacts.getCustomerId();
+                    }
+                }
+                callInAction(callerEE.getCompanyId(),customerId,callerEE.getCompanyUserId(),session,caller,callerEE);
+            }
         }
         CallResult result=new CallResult();
         result.setMsg("");
@@ -161,6 +209,64 @@ public class VoiceApiController extends AppBaseController {
         return result;
     }
 
+    private  R callInAction(Long companyId, Long customerId, Long userId,String session,String caller,CompanyVoiceCaller callerEE){
+        //查询主叫号是不是坐席 查询主叫号是否已过期
+        Company company=companyService.selectCompanyById(companyId);
+        if(company.getStatus()==0){
+            return R.error("公司已停用");
+        }
+        if(company.getVoiceApiId()==null){
+            return R.error("未配置外呼接口");
+        }
+        CompanyVoiceApi api=companyVoiceApiService.selectCompanyVoiceApiById(company.getVoiceApiId());
+        if(api==null){
+            return R.error("外呼接口不存在");
+        }
+        if(api.getStatus().equals(0)){
+            return R.error("外呼接口已禁用");
+        }
+        CompanyUser user=userService.selectCompanyUserById(userId);
+        //CompanyVoiceCaller voiceCaller=callerService.selectCompanyVoiceCallerByUserId(companyId,userId);
+        CompanyVoice companyVoice=companyVoiceService.selectCompanyVoiceByCompanyId(user.getCompanyId());
+        if(callerEE==null){
+            return R.error("未绑定坐席");
+        }
+        if(companyVoice.getTimes()<=0){
+            return R.error("剩余时长不足,请购买套餐");
+        }
+
+//      CompanyVoiceMobile voiceMobile=mobileService.selectEmptyCompanyVoiceMobile(companyId,api.getApiId());
+//      if(voiceMobile==null){
+//           return R.error("没有空闲号码");
+//      }
+
+        //黑名单处理
+        if(blacklistService.selectCompanyVoiceBlacklistByMobile(caller)>0){
+            return R.error("主叫号码已被设置为黑名单");
+        }
+        //写入SESSION
+        CompanyVoiceLogs logs=new CompanyVoiceLogs();
+        logs.setCompanyId(companyId);
+        logs.setVoiceTitle(caller+"回拨:"+user.getNickName());
+        logs.setStartTime(new Date());
+        logs.setVoiceType(1);
+        logs.setCalleePhone(callerEE.getMobile());
+        logs.setCallerPhone(caller);
+        logs.setDisplayCalleeNumber(callerEE.getMobile());
+        logs.setDisplayCallerNumber(caller);
+        logs.setRemark(caller +"回拨呼叫"+user.getNickName());
+        logs.setCompanyUserId(userId);
+        logs.setCustomerId(customerId);
+        logs.setApiId(api.getApiId());
+        logs.setSessionId(session);
+        logs.setCallerNo(caller);
+        logsService.insertCompanyVoiceLogs(logs);
+//        voiceMobile.setStatus(0);
+//        mobileService.updateCompanyVoiceMobile(voiceMobile);
+        return R.ok();
+
+    }
+
     @Login
     @ApiOperation("获取SIP")
     @GetMapping(value="/getSipAccount")

+ 0 - 137
fs-company-app/src/main/resources/application-druid-fby.yml

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

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

@@ -4,7 +4,6 @@ server:
 
 spring:
   profiles:
-    active: dev
-    include: common,config-dev
+    active: druid-zkzh-test
 #    active: druid-fby
 #    include: common,config-fby

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

@@ -13,12 +13,15 @@ import com.fs.common.utils.ServletUtils;
 import com.fs.common.utils.poi.ExcelUtil;
 import com.fs.company.domain.Company;
 import com.fs.company.domain.CompanyRecharge;
+import com.fs.company.domain.CompanyRechargeOrder;
+import com.fs.company.dto.RechargeDTO;
 import com.fs.company.param.CompanyRechargeParam;
 import com.fs.company.service.ICompanyRechargeService;
 import com.fs.company.service.ICompanyService;
 import com.fs.company.vo.CompanyRechargeVO;
 import com.fs.core.security.LoginUser;
 import com.fs.core.web.service.TokenService;
+import com.tencentcloudapi.organization.v20181225.OrganizationErrorCode;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.transaction.annotation.Transactional;
@@ -75,6 +78,38 @@ public class CompanyRechargeController extends BaseController
     }
 
 
+    /**
+     * 充值
+     * @return AjaxResult
+     */
+    @PostMapping("/wxRecharge")
+    public AjaxResult recharge(@RequestBody RechargeDTO dto){
+        CompanyRechargeOrder companyRechargeOrder;
+        try {
+            LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+
+            dto.setCompanyId(loginUser.getCompany().getCompanyId());
+            dto.setUserId(loginUser.getUser().getUserId());
+            companyRechargeOrder = companyRechargeService.recharge(dto);
+        }catch (Exception e) {
+            logger.error("给公司充值失败",e);
+            return AjaxResult.error(e.getMessage());
+        }
+        return AjaxResult.success(companyRechargeOrder);
+    }
+
+    /**
+     * 查询订单
+     * @param orderNo 订单号
+     * @return AjaxResult
+     */
+    @GetMapping("/queryOrder")
+    public AjaxResult queryOrder(@RequestParam("orderNo") String orderNo) {
+        CompanyRechargeOrder order = companyRechargeService.queryOrder(orderNo);
+
+        return AjaxResult.success(order);
+    }
+
 
     /**
      * 新增充值

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

@@ -355,5 +355,21 @@ public class CompanyUserController extends BaseController {
             return AjaxResult.error("操作失败");
         }
     }
+    @PutMapping("/updateVolume")
+    public AjaxResult updateVolume(@RequestBody CompanyUser user) {
+        user.setUpdateBy(SecurityUtils.getUsername());
+        return toAjax(companyUserService.updateVolume(user));
+    }
+
+    @Log(title = "是否允许所有方式注册会员", businessType = BusinessType.UPDATE)
+    @PutMapping("/allowedAllRegister")
+    public AjaxResult isAllowedAllRegister(@RequestParam Boolean status, @RequestBody List<Long> userIds) {
+        Boolean r = companyUserService.isAllowedAllRegister(status, userIds);
+        if (r) {
+            return AjaxResult.success();
+        } else {
+            return AjaxResult.error("操作失败");
+        }
+    }
 
 }

+ 18 - 0
fs-company/src/main/java/com/fs/course/controller/FsUserWatchCourseStatisticsController.java

@@ -46,6 +46,12 @@ public class FsUserWatchCourseStatisticsController extends BaseController
         LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
         fsUserWatchCourseStatistics.setCompanyId( loginUser.getCompany().getCompanyId());
         List<FsUserWatchCourseStatistics> list = fsUserWatchCourseStatisticsService.selectFsUserWatchCourseStatisticsList(fsUserWatchCourseStatistics);
+        if(!list.isEmpty()){
+            for (FsUserWatchCourseStatistics userWatchCourseStatistics : list) {
+                userWatchCourseStatistics.setCompleteWatchRatePercent(userWatchCourseStatistics.getCompleteWatchRate() + "%");
+                userWatchCourseStatistics.setAnswerRightRatePercent(userWatchCourseStatistics.getAnswerRightRate() + "%");
+            }
+        }
         return getDataTable(list);
     }
 
@@ -57,6 +63,12 @@ public class FsUserWatchCourseStatisticsController extends BaseController
         LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
         fsUserWatchCourseStatistics.setCompanyId( loginUser.getCompany().getCompanyId());
         List<FsUserWatchCourseStatistics> list = fsUserWatchCourseStatisticsService.selectFsUserWatchCourseStatisticsList(fsUserWatchCourseStatistics);
+        if(!list.isEmpty()){
+            for (FsUserWatchCourseStatistics userWatchCourseStatistics : list) {
+                userWatchCourseStatistics.setCompleteWatchRatePercent(userWatchCourseStatistics.getCompleteWatchRate() + "%");
+                userWatchCourseStatistics.setAnswerRightRatePercent(userWatchCourseStatistics.getAnswerRightRate() + "%");
+            }
+        }
         ExcelUtil<FsUserWatchCourseStatistics> util = new ExcelUtil<FsUserWatchCourseStatistics>(FsUserWatchCourseStatistics.class);
         return util.exportExcel(list, "会员观看数据明细");
     }
@@ -72,6 +84,11 @@ public class FsUserWatchCourseStatisticsController extends BaseController
         LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
         fsUserWatchCourseStatistics.setCompanyId( loginUser.getCompany().getCompanyId());
         List<FsUserWatchCourseStatistics> list = fsUserWatchCourseStatisticsService.selectFsUserWatchCourseStatisticsListTotal(fsUserWatchCourseStatistics);
+        if(!list.isEmpty()){
+            for (FsUserWatchCourseStatistics userWatchCourseStatistics : list) {
+                userWatchCourseStatistics.setCompleteWatchRatePercent(userWatchCourseStatistics.getCompleteWatchRate() + "%");
+            }
+        }
         return getDataTable(list);
     }
 
@@ -88,6 +105,7 @@ public class FsUserWatchCourseStatisticsController extends BaseController
         List<FsUserWatchCourseStatisticsExportVO> listVO = list.stream().map(v -> {
             FsUserWatchCourseStatisticsExportVO vo = new FsUserWatchCourseStatisticsExportVO();
             BeanUtils.copyProperties(v, vo);
+            vo.setCompleteWatchRatePercent(v.getCompleteWatchRate() + "%");
             return vo;
         }).collect(Collectors.toList());
         ExcelUtil<FsUserWatchCourseStatisticsExportVO> util = new ExcelUtil<FsUserWatchCourseStatisticsExportVO>(FsUserWatchCourseStatisticsExportVO.class);

+ 29 - 3
fs-company/src/main/java/com/fs/crm/controller/CrmCustomerController.java

@@ -13,12 +13,14 @@ import com.fs.common.utils.StringUtils;
 import com.fs.common.utils.poi.ExcelUtil;
 import com.fs.company.domain.CompanyUser;
 import com.fs.company.service.ICompanyUserService;
+import com.fs.crm.domain.CrmCustomerContacts;
 import com.fs.crm.param.CrmCompanyLineCustomerImportParam;
 import com.fs.core.security.LoginUser;
 import com.fs.core.web.service.TokenService;
 import com.fs.crm.domain.CrmCustomer;
 import com.fs.crm.param.*;
 import com.fs.crm.service.ICrmCustomerAssistService;
+import com.fs.crm.service.ICrmCustomerContactsService;
 import com.fs.crm.service.ICrmCustomerService;
 import com.fs.crm.service.ICrmCustomerUserService;
 import com.fs.crm.service.impl.CrmCustomerAssistServiceImpl;
@@ -55,8 +57,7 @@ public class CrmCustomerController extends BaseController
     @Autowired
     ICrmCustomerUserService crmCustomerUserService;
     @Autowired
-    private ICrmCustomerAssistService crmCustomerAssistService;
-
+    private ICrmCustomerContactsService crmContactsService;
     @ApiOperation("获取线索客户")
     @PreAuthorize("@ss.hasPermi('crm:customer:lineList')")
     @GetMapping("/getLineCustomerList")
@@ -249,7 +250,7 @@ public class CrmCustomerController extends BaseController
         }
         LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
         param.setCompanyId(loginUser.getCompany().getCompanyId());
-        return crmCustomerAssistService.assistToUser(loginUser.getUsername(),loginUser.getUser().getUserId(),param);
+        return crmCustomerService.assistToUser(loginUser.getUsername(),loginUser.getUser().getUserId(),param);
     }
 
 
@@ -453,4 +454,29 @@ public class CrmCustomerController extends BaseController
         return R.ok().put("data",list);
     }
 
+    @ApiOperation("置顶切换")
+    @PreAuthorize("@ss.hasPermi('crm:customer:switchToTop')")
+    @PostMapping("/switchToTop/{customerId}")
+    public R switchToTop(@PathVariable Long customerId) {
+        crmCustomerService.switchToTop(customerId);
+        return R.ok();
+    }
+    @PreAuthorize("@ss.hasPermi('crm:customer:query2')")
+    @GetMapping(value = "/getInfoByMobile/{mobile}")
+    public R getInfoByMobile(@PathVariable("mobile") String mobile)
+    {
+        CrmCustomer customer=crmCustomerService.selectFscrmByMobile(mobile);
+        Long customerId=0L;
+        if(customer==null){
+            CrmCustomerContacts contactsMap=new CrmCustomerContacts();
+            contactsMap.setMobile(mobile);
+            List<CrmCustomerContacts>  contactsList=crmContactsService.selectCrmCustomerContactsList(contactsMap);
+            if(contactsList.size()>0){
+                CrmCustomerContacts contacts=contactsList.get(0);
+                customerId=contacts.getCustomerId();
+                customer=crmCustomerService.selectCrmCustomerById(customerId);
+            }
+        }
+        return R.ok().put("data",customer);
+    }
 }

+ 40 - 0
fs-company/src/main/java/com/fs/crm/controller/CrmCustomerLevelController.java

@@ -0,0 +1,40 @@
+package com.fs.crm.controller;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.R;
+import com.fs.crm.domain.CrmCustomerLevel;
+import com.fs.crm.service.ICrmCustomerLevelService;
+import com.fs.his.vo.OptionsVO;
+import lombok.AllArgsConstructor;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.List;
+import java.util.Objects;
+import java.util.stream.Collectors;
+
+@RestController
+@RequestMapping("/crm/customerLevel")
+@AllArgsConstructor
+public class CrmCustomerLevelController extends BaseController {
+
+    private final ICrmCustomerLevelService customerLevelService;
+
+    @GetMapping("/getCustomerLevelOption")
+    public R getCustomerLevelOption(Integer status) {
+        LambdaQueryWrapper<CrmCustomerLevel> wrapper = Wrappers.lambdaQuery();
+        if (Objects.nonNull(status)) {
+            wrapper.eq(CrmCustomerLevel::getStatus, status);
+        }
+        List<OptionsVO> options = customerLevelService.list(wrapper).stream().map(l -> {
+            OptionsVO vo = new OptionsVO();
+            vo.setDictLabel(l.getName());
+            vo.setDictValue(l.getId());
+            return vo;
+        }).collect(Collectors.toList());
+        return R.ok().put("data", options);
+    }
+}

+ 20 - 28
fs-company/src/main/java/com/fs/pay/controller/WxPayController.java

@@ -7,6 +7,8 @@ import com.fs.common.utils.StringUtils;
 import com.fs.company.domain.CompanyRecharge;
 import com.fs.company.service.ICompanyRechargeService;
 import com.fs.pay.bean.WxPayBean;
+import com.fs.wx.pay.config.WxPayProperties;
+import com.github.binarywang.wxpay.util.SignUtils;
 import com.ijpay.core.enums.SignType;
 import com.ijpay.core.enums.TradeType;
 import com.ijpay.core.kit.HttpKit;
@@ -45,6 +47,8 @@ public class WxPayController extends WxPayApiController {
     @Autowired
     ICompanyRechargeService rechargeService;
 
+    @Autowired
+    private WxPayProperties wxPayProperties;
 
 
     @Override
@@ -147,44 +151,32 @@ public class WxPayController extends WxPayApiController {
     public String payNotify(HttpServletRequest request) {
         // 支付结果通用通知文档: https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_7
         String xmlMsg = HttpKit.readData(request);
-        System.out.println("支付通知="+xmlMsg);
+        log.info("支付通知 {}", xmlMsg);
         Map<String, String> params = WxPayKit.xmlToMap(xmlMsg);
         String returnCode = params.get("return_code");
         // 微信支付订单号
-        String transaction_id      = params.get("transaction_id");
+        String transaction_id = params.get("transaction_id");
         // 商户订单号
-        String out_trade_no      = params.get("out_trade_no");
+        String out_trade_no = params.get("out_trade_no");
         // 注意重复通知的情况,同一订单号可能收到多次通知,请注意一定先判断订单状态
-        // 注意此处签名方式需与统一下单的签名类型一致
-        if (WxPayKit.verifyNotify(params, WxPayApiConfigKit.getWxPayApiConfig().getPartnerKey(), SignType.HMACSHA256)) {
+        // 注意此处签名方式需与统一下单的签名类型一致1
+        if (SignUtils.checkSign(params, String.valueOf(SignType.HMACSHA256), wxPayProperties.getMchKey())) {
             if (WxPayKit.codeIsOk(returnCode)) {
                 // 更新订单信息
                 // 发送通知等
                 String[] order=out_trade_no.split("-");
                 R r;
-                switch (order[0]){
-                    case "recharge":
-                        CompanyRecharge recharge=rechargeService.selectCompanyRechargeByNo(order[1]);
-
-                        if(recharge!=null&&recharge.getStatus()==1){
-                            Map<String, String> xml = new HashMap<String, String>(2);
-                            xml.put("return_code", "SUCCESS");
-                            xml.put("return_msg", "OK");
-                            return WxPayKit.toXml(xml);
-                        }
-                        recharge.setTradeNo(transaction_id);
-                        r= rechargeService.payNotify(recharge);
-                        if(r.get("code").equals(200)){
-                            Map<String, String> xml = new HashMap<String, String>(2);
-                            xml.put("return_code", "SUCCESS");
-                            xml.put("return_msg", "OK");
-                            return WxPayKit.toXml(xml);
-
-                        }
-                        else {
-                            return null;
-                        }
-
+                if (order[0].equals("recharge")) {
+                    r = rechargeService.payNotify(order[1],transaction_id);
+                    if (r.get("code").equals(200)) {
+                        Map<String, String> xml = new HashMap<String, String>(2);
+                        xml.put("return_code", "SUCCESS");
+                        xml.put("return_msg", "OK");
+                        return WxPayKit.toXml(xml);
+
+                    } else {
+                        return null;
+                    }
                 }
             }
         }

+ 1 - 1
fs-company/src/main/java/com/fs/users/controller/FsUserController.java

@@ -133,7 +133,7 @@ public class FsUserController extends BaseController
         LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
         param.setUserId(loginUser.getUser().getUserId());
 //        startPage();
-        PageHelper.startPage(param.getPageNum(), param.getPageSize());
+//        PageHelper.startPage(param.getPageNum(), param.getPageSize());
         PageInfo<FsUserPageListVO> fsUserPageListVOPageInfo = fsUserService.selectFsUserPageList(param);
         Map<String, Object> map = new HashMap<String, Object>();
         map.put("rows", fsUserPageListVOPageInfo.getList());

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

@@ -5,6 +5,6 @@ server:
 spring:
   profiles:
     active: dev
-    include: common,config-dev
+#    include: common,config-dev
 #    active: druid-fby
 #    include: common,config-fby

+ 1 - 1
fs-qw-task/src/main/resources/application.yml

@@ -5,4 +5,4 @@ server:
 spring:
   profiles:
     active: dev
-    include: common,config-dev
+#    include: common,config-dev

+ 83 - 0
fs-service-system/src/main/java/com/fs/company/constant/PaymentStatus.java

@@ -0,0 +1,83 @@
+package com.fs.company.constant;
+
+import lombok.Getter;
+
+/**
+ * 支付状态枚举类
+ *
+ * 描述支付过程中可能的状态
+ */
+@Getter
+public enum PaymentStatus {
+
+    /**
+     * 支付创建,初始状态
+     */
+    CREATED(0, "创建"),
+
+    /**
+     * 支付处理中
+     */
+    PROCESSING(1, "处理中"),
+
+    /**
+     * 支付成功
+     */
+    SUCCESS(2, "支付成功"),
+
+    /**
+     * 支付失败
+     */
+    FAILED(3, "支付失败");
+
+    /**
+     * 状态码
+     * -- GETTER --
+     *  获取状态码
+     *
+     * @return 状态码
+
+     */
+    private final int code;
+
+    /**
+     * 状态描述
+     * -- GETTER --
+     *  获取状态描述
+     *
+     * @return 状态描述
+
+     */
+    private final String description;
+
+    /**
+     * 构造函数
+     *
+     * @param code 状态码
+     * @param description 状态描述
+     */
+    PaymentStatus(int code, String description) {
+        this.code = code;
+        this.description = description;
+    }
+
+    /**
+     * 根据状态码获取对应的枚举值
+     *
+     * @param code 状态码
+     * @return 对应的支付状态枚举,如果没找到则返回null
+     */
+    public static PaymentStatus getByCode(int code) {
+        for (PaymentStatus status : PaymentStatus.values()) {
+            if (status.getCode() == code) {
+                return status;
+            }
+        }
+        return null;
+    }
+
+    @Override
+    public String toString() {
+        return code + ":" + description;
+    }
+}

+ 75 - 0
fs-service-system/src/main/java/com/fs/company/domain/CompanyRechargeOrder.java

@@ -0,0 +1,75 @@
+package com.fs.company.domain;
+
+import lombok.Data;
+import lombok.Builder;
+import lombok.NoArgsConstructor;
+import lombok.AllArgsConstructor;
+
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+/**
+ * 公司充值订单表
+ */
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class CompanyRechargeOrder {
+
+    /**
+     * 主键ID
+     */
+    private Long id;
+
+    /**
+     * 订单号
+     */
+    private String orderNo;
+
+    /**
+     * 支付平台交易号
+     */
+    private String transactionId;
+
+    /**
+     * 支付方式:1-微信 2-支付宝 3-银行卡 4-其他
+     */
+    private Integer payType;
+
+    /**
+     * 支付金额
+     */
+    private BigDecimal payAmount;
+
+    private Long companyId;
+
+    private Long userId;
+
+    /**
+     * 支付状态:0-创建 1-处理中 2-支付成功 3-支付失败
+     */
+    private Integer payStatus;
+
+    /**
+     * 支付时间
+     */
+    private LocalDateTime paymentTime;
+
+    /**
+     * 回调内容
+     */
+    private String callbackContent;
+
+    /**
+     * 创建时间
+     */
+    private LocalDateTime createTime;
+
+    /**
+     * 更新时间
+     */
+    private LocalDateTime updateTime;
+
+    private String qrLink;
+}

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

@@ -132,6 +132,10 @@ public class CompanyUser extends BaseEntity
 
     private Integer qwStatus;
 
+    /** 音量 */
+    private double volume;
+
+
     /** 用户上级id */
     private Long parentId;
 
@@ -144,6 +148,16 @@ public class CompanyUser extends BaseEntity
     /** 是否需要单独注册会员,1-是,0-否(用于个微销售分享看课) */
     private Integer isNeedRegisterMember;
 
+    /** 是否允许所有方式注册会员,1-是,0-否,默认1(用于个微注册会员) */
+    private Integer isAllowedAllRegister;
+
+    public double getVolume() {
+        return volume;
+    }
+
+    public void setVolume(double volume) {
+        this.volume = volume;
+    }
     public Integer getIsAudit() {
         return isAudit;
     }
@@ -504,4 +518,12 @@ public class CompanyUser extends BaseEntity
     public void setPosts(List<CompanyPost> posts) {
         this.posts = posts;
     }
+
+    public Integer getIsAllowedAllRegister() {
+        return isAllowedAllRegister;
+    }
+
+    public void setIsAllowedAllRegister(Integer isAllowedAllRegister) {
+        this.isAllowedAllRegister = isAllowedAllRegister;
+    }
 }

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

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

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

@@ -13,6 +13,7 @@ import org.apache.ibatis.annotations.Update;
 import java.math.BigDecimal;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
 /**
  * 企业Mapper接口
@@ -158,4 +159,6 @@ public interface CompanyMapper
 
     List<Company> selectCompanyAllList();
 
+    List<Company> selectCompanyByIds(@Param("companyIds") Set<Long> companyIds);
+
 }

+ 74 - 0
fs-service-system/src/main/java/com/fs/company/mapper/CompanyRechargeOrderMapper.java

@@ -0,0 +1,74 @@
+package com.fs.company.mapper;
+
+import com.fs.company.domain.CompanyRechargeOrder;
+import org.apache.ibatis.annotations.*;
+
+import java.util.List;
+
+/**
+ * 公司充值订单表 Mapper
+ */
+@Mapper
+public interface CompanyRechargeOrderMapper {
+
+    /**
+     * 根据ID查询订单
+     */
+    @Select("SELECT * FROM company_recharge_order WHERE id = #{id}")
+    CompanyRechargeOrder selectById(Long id);
+
+    /**
+     * 根据订单号查询订单
+     */
+    @Select("SELECT * FROM company_recharge_order WHERE order_no = #{orderNo}")
+    CompanyRechargeOrder selectByOrderNo(String orderNo);
+
+    /**
+     * 根据交易号查询订单
+     */
+    @Select("SELECT * FROM company_recharge_order WHERE transaction_id = #{transactionId}")
+    CompanyRechargeOrder selectByTransactionId(String transactionId);
+
+    /**
+     * 查询所有订单
+     */
+    @Select("SELECT * FROM company_recharge_order")
+    List<CompanyRechargeOrder> selectAll();
+
+    /**
+     * 新增订单
+     */
+    @Insert("INSERT INTO company_recharge_order (order_no, transaction_id, pay_type, pay_amount, pay_status, payment_time, callback_content,company_id,user_id) " +
+            "VALUES (#{orderNo}, #{transactionId}, #{payType}, #{payAmount}, #{payStatus}, #{paymentTime}, #{callbackContent},#{companyId},#{userId})")
+    @Options(useGeneratedKeys = true, keyProperty = "id")
+    int insert(CompanyRechargeOrder order);
+
+    /**
+     * 更新订单
+     */
+    @Update("UPDATE company_recharge_order SET " +
+            "transaction_id = #{transactionId}, " +
+            "pay_type = #{payType}, " +
+            "pay_amount = #{payAmount}, " +
+            "pay_status = #{payStatus}, " +
+            "payment_time = #{paymentTime}, " +
+            "callback_content = #{callbackContent} " +
+            "WHERE order_no = #{orderNo}")
+    int updateByOrderNo(CompanyRechargeOrder order);
+
+    /**
+     * 更新订单支付状态
+     */
+    @Update("UPDATE company_recharge_order SET " +
+            "pay_status = #{payStatus}, " +
+            "payment_time = #{paymentTime}, " +
+            "transaction_id = #{transactionId}, " +
+            "callback_content = #{callbackContent} " +
+            "WHERE order_no = #{orderNo}")
+    int updatePayStatus(CompanyRechargeOrder order);
+
+    @Select("SELECT * FROM company_recharge_order " +
+            "WHERE pay_status = 1 " +
+            "AND create_time <= DATE_SUB(NOW(), INTERVAL 2 HOUR)")
+    List<CompanyRechargeOrder> queryOverdueOrder();
+}

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

@@ -291,4 +291,11 @@ public interface CompanyUserMapper
     List<CompanyUser> selectAllCompanyUserByCompanyIdAndDeptId(@Param("companyId") Long companyId, @Param("deptId") Long deptId);
 
     List<String> selectCompanyUserNameByIds(@Param("companyUserIDs")List<Long> companyUserID);
+
+
+    @Update(" update company_user set volume=#{maps.volume} where user_id=#{maps.userId} ")
+    public int updateVolume(@Param("maps") CompanyUser user);
+
+    int updateAllowedAllRegister(@Param("status") boolean status, @Param("userIds")List<Long> userIds);
+
 }

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

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

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

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

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

@@ -204,4 +204,14 @@ public interface ICompanyUserService {
      */
     Boolean setIsRegisterMember(boolean status,  List<Long> userIds);
 
+    int updateVolume(CompanyUser user);
+
+    /**
+     * 批量设置是否允许所有方式注册会员
+     * @param status 开/关
+     * @param userIds 员工id
+     * @return true/false
+     */
+    Boolean isAllowedAllRegister(boolean status,  List<Long> userIds);
+
 }

+ 2 - 0
fs-service-system/src/main/java/com/fs/company/service/ICompanyVoiceCallerService.java

@@ -73,4 +73,6 @@ public interface ICompanyVoiceCallerService
     List<CompanyVoiceCaller> selectCompanyVoiceCallerByEnable(Long callerLine);
 
     Integer selectCompanyVoiceCallerCountsByCompanyId(Long companyId);
+
+    CompanyVoiceCaller selectCompanyVoiceCallerByCallerNo(String callee);
 }

+ 101 - 0
fs-service-system/src/main/java/com/fs/company/service/impl/CompanyRechargeOrderServiceImpl.java

@@ -0,0 +1,101 @@
+package com.fs.company.service.impl;
+
+import com.alibaba.fastjson.JSON;
+import com.fs.common.utils.IpUtil;
+import com.fs.common.utils.OrderUtils;
+import com.fs.company.constant.PaymentStatus;
+import com.fs.company.domain.CompanyRechargeOrder;
+import com.fs.company.mapper.CompanyRechargeOrderMapper;
+import com.fs.company.service.CompanyRechargeOrderService;
+import com.fs.wx.pay.config.WxPayProperties;
+import com.github.binarywang.wxpay.bean.order.WxPayMpOrderResult;
+import com.github.binarywang.wxpay.bean.order.WxPayNativeOrderResult;
+import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
+import com.github.binarywang.wxpay.config.WxPayConfig;
+import com.github.binarywang.wxpay.constant.WxPayConstants;
+import com.github.binarywang.wxpay.service.WxPayService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Propagation;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+import java.util.List;
+
+@Service
+public class CompanyRechargeOrderServiceImpl implements CompanyRechargeOrderService {
+    @Autowired
+    private CompanyRechargeOrderMapper companyRechargeOrderMapper;
+
+    @Autowired
+    private WxPayProperties wxPayProperties;
+
+    @Autowired
+    private WxPayService wxPayService;
+    @Override
+    public List<CompanyRechargeOrder> queryOverdueOrder() {
+        return companyRechargeOrderMapper.queryOverdueOrder();
+    }
+
+    /**
+     * 自动关闭超时订单号
+     */
+    @Override
+    public void autoClosedOrder(){
+        List<CompanyRechargeOrder> companyRechargeOrders = companyRechargeOrderMapper.queryOverdueOrder();
+        for (CompanyRechargeOrder order : companyRechargeOrders) {
+            order.setPayStatus(PaymentStatus.FAILED.getCode());
+            companyRechargeOrderMapper.updateByOrderNo(order);
+        }
+    }
+
+    @Override
+    @Transactional(rollbackFor = Throwable.class,propagation = Propagation.REQUIRED)
+    public CompanyRechargeOrder createOrder(CompanyRechargeOrder order) throws Exception{
+
+        WxPayConfig payConfig = new WxPayConfig();
+        payConfig.setAppId(wxPayProperties.getAppId());
+        payConfig.setMchId(wxPayProperties.getMchId());
+        payConfig.setMchKey(wxPayProperties.getMchKey());
+        payConfig.setPrivateKeyPath(wxPayProperties.getPrivateKeyPath());
+        payConfig.setPrivateCertPath(wxPayProperties.getPrivateCertPath());
+        payConfig.setCertSerialNo(wxPayProperties.getCertSerialNo());
+        payConfig.setUseSandboxEnv(false);
+        payConfig.setSignType(WxPayConstants.SignType.HMAC_SHA256);
+
+        wxPayService.setConfig(payConfig);
+
+        WxPayUnifiedOrderRequest orderRequest = new WxPayUnifiedOrderRequest();
+        String orderNo = OrderUtils.getOrderNo();
+        orderRequest.setBody("公司余额充值");
+        orderRequest.setOutTradeNo("recharge-"+orderNo);
+        orderRequest.setTotalFee(order.getPayAmount().multiply(BigDecimal.valueOf(100)).intValue());
+        orderRequest.setSpbillCreateIp(IpUtil.getLocalhostIp());
+        orderRequest.setNotifyUrl(wxPayProperties.getNativeNotifyUrl());
+        orderRequest.setTradeType(WxPayConstants.TradeType.NATIVE);
+        orderRequest.setProductId(String.valueOf(order.getId()));
+
+
+        WxPayNativeOrderResult wxOrder = wxPayService.createOrder(orderRequest);
+
+
+        order.setOrderNo(orderNo);
+        order.setPayType(1);
+        order.setPayStatus(1);
+        order.setCreateTime(LocalDateTime.now());
+        order.setCallbackContent(JSON.toJSONString(wxOrder));
+        order.setQrLink(wxOrder.getCodeUrl());
+
+        companyRechargeOrderMapper.insert(order);
+
+        return order;
+    }
+
+    @Override
+    public CompanyRechargeOrder queryOrder(String orderNo) {
+        return companyRechargeOrderMapper.selectByOrderNo(orderNo);
+    }
+
+
+}

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

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

+ 7 - 1
fs-service-system/src/main/java/com/fs/company/service/impl/CompanyTagUserServiceImpl.java

@@ -118,8 +118,14 @@ public class CompanyTagUserServiceImpl implements ICompanyTagUserService
                 keywords = param.getKeyword().split(",");
             }
         }
+        // 判断是否是管理员
+        Long companyId = null;
+        CompanyUser companyUser = companyUserMapper.selectCompanyUserById(param != null ? param.getUserId() : null);
+        if (companyUser != null && companyUser.isAdmin()){
+            companyId = companyUser.getCompanyId();
+        }
         //获取所有销售
-        List<CompanyUser> companyUsers = companyUserMapper.selectAllCompanyUserAndSelf(param != null ? param.getUserId() : null,null);
+        List<CompanyUser> companyUsers = companyUserMapper.selectAllCompanyUserAndSelf(param != null ? param.getUserId() : null, companyId);
         List<Long> userIds = Collections.emptyList();
         if(companyUsers != null && !companyUsers.isEmpty()){
             userIds = companyUsers.stream().map(CompanyUser::getUserId).collect(Collectors.toList());

+ 19 - 2
fs-service-system/src/main/java/com/fs/company/service/impl/CompanyUserServiceImpl.java

@@ -494,13 +494,17 @@ public class CompanyUserServiceImpl implements ICompanyUserService
     }
 
     @Override
+    @Transactional
     public int changeCompanyUser(List<Long> userIds, Long companyUserId, Long companyId) {
 
         CompanyUser toUser = companyUserMapper.selectCompanyUserById(companyUserId);
         if (Objects.isNull(toUser)) {
             throw new ServiceException("需要更换归属的销售不存在");
         }
-       return fsUserMapper.batchUpdateUserCompanyUser(userIds, companyUserId, companyId);
+       fsUserMapper.batchUpdateUserCompanyUser(userIds, companyUserId, companyId);
+        // 修改中间表
+        fsUserMapper.batchUpdateCompanyUserRelation(userIds, companyUserId, companyId);
+        return 1;
     }
 
     /**
@@ -523,6 +527,16 @@ public class CompanyUserServiceImpl implements ICompanyUserService
         return true;
     }
 
+    @Override
+    public Boolean isAllowedAllRegister(boolean status, List<Long> userIds) {
+        try {
+            companyUserMapper.updateAllowedAllRegister(status, userIds);
+        } catch (RuntimeException e) {
+            throw new ServiceException("操作异常");
+        }
+        return true;
+    }
+
     /**
      * 批量审核用户
      * @param userIds 用户ID集合
@@ -545,5 +559,8 @@ public class CompanyUserServiceImpl implements ICompanyUserService
     public List<CompanyUser> getCompanyUserListByCompanyIdAndDeptId(Long companyId, Long deptId) {
         return companyUserMapper.selectAllCompanyUserByCompanyIdAndDeptId(companyId, deptId);
     }
-
+    @Override
+    public int updateVolume(CompanyUser user){
+        return companyUserMapper.updateVolume(user);
+    }
 }

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

@@ -190,4 +190,10 @@ public class CompanyVoiceCallerServiceImpl implements ICompanyVoiceCallerService
     public Integer selectCompanyVoiceCallerCountsByCompanyId(Long companyId) {
         return companyVoiceCallerMapper.selectCompanyVoiceCallerCountsByCompanyId(companyId);
     }
+
+    @Override
+    public CompanyVoiceCaller selectCompanyVoiceCallerByCallerNo(String callerNo) {
+        return companyVoiceCallerMapper.selectCompanyVoiceCallerByCallerNo(callerNo);
+    }
+
 }

+ 4 - 0
fs-service-system/src/main/java/com/fs/company/vo/CompanyUserQwListVO.java

@@ -119,4 +119,8 @@ public class CompanyUserQwListVO extends BaseEntity {
 
     /** 是否需要单独注册会员,1-是,0-否*/
     private Integer isNeedRegisterMember;
+
+    /** 是否允许所有方式注册会员,1-是,0-否,默认1(用于个微注册会员) */
+    private Integer isAllowedAllRegister;
+
 }

+ 3 - 0
fs-service-system/src/main/java/com/fs/config/cloud/CloudHostProper.java

@@ -9,4 +9,7 @@ import org.springframework.stereotype.Component;
 public class CloudHostProper {
     @Value("${cloud_host.company_name}")
     private String companyName;
+
+    @Value("${headerImg.imgUrl}")
+    private String headerImg;
 }

+ 10 - 2
fs-service-system/src/main/java/com/fs/course/domain/FsUserWatchCourseStatistics.java

@@ -89,9 +89,13 @@ public class FsUserWatchCourseStatistics extends BaseEntity{
     private Integer completeWatchNum;
 
     /** 完播率 */
-    @Excel(name = "完播率")
+//    @Excel(name = "完播率")
     private BigDecimal completeWatchRate;
 
+    /** 完播率+% */
+    @Excel(name = "完播率")
+    private String completeWatchRatePercent;
+
     /** 答题人数 */
     @Excel(name = "答题人数")
     private Integer answerNum;
@@ -101,9 +105,13 @@ public class FsUserWatchCourseStatistics extends BaseEntity{
     private Integer answerRightNum;
 
     /** 答题正确率 */
-    @Excel(name = "正确率")
+//    @Excel(name = "正确率")
     private BigDecimal answerRightRate;
 
+    /** 答题正确率+% */
+    @Excel(name = "正确率")
+    private String answerRightRatePercent;
+
     /** 红包领取数量 */
     @Excel(name = "红包领取个数")
     private Integer redPacketNum;

+ 4 - 1
fs-service-system/src/main/java/com/fs/course/domain/FsUserWatchStatistics.java

@@ -61,8 +61,11 @@ public class FsUserWatchStatistics extends BaseEntity{
     private Integer completeWatchNum;
 
     /** 完播率 */
-    @Excel(name = "完播率")
+//    @Excel(name = "完播率")
     private BigDecimal completeWatchRate;
 
+    /** 完播率+% */
+    @Excel(name = "完播率")
+    private String completeWatchRatePercent;
 
 }

+ 1 - 1
fs-service-system/src/main/java/com/fs/course/mapper/FsUserCourseCategoryMapper.java

@@ -86,7 +86,7 @@ public interface FsUserCourseCategoryMapper
      * 查询所有分类
      * @return
      */
-    @Select("select cate_id,cate_name, pid from fs_user_course_category where is_del=0")
+    @Select("select cate_id as cateId, cate_name as cateName, pid from fs_user_course_category where is_del=0")
     @MapKey("cateName")
     Map<String,FsUserCourseCategory> queryAllCategoryData();
 

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

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

+ 6 - 2
fs-service-system/src/main/java/com/fs/course/service/impl/FsCourseLinkServiceImpl.java

@@ -8,6 +8,7 @@ import com.fs.common.utils.DateUtils;
 import com.fs.common.utils.StringUtils;
 import com.fs.company.domain.CompanyUser;
 import com.fs.company.mapper.CompanyUserMapper;
+import com.fs.config.cloud.CloudHostProper;
 import com.fs.course.config.CourseConfig;
 import com.fs.course.domain.FsCourseDomainName;
 import com.fs.course.domain.FsCourseLink;
@@ -64,6 +65,9 @@ public class FsCourseLinkServiceImpl implements IFsCourseLinkService
     @Autowired
     private CompanyUserMapper companyUserMapper;
 
+    @Autowired
+    CloudHostProper cloudHostProper;
+
 
     /**
      * 查询短链
@@ -258,14 +262,14 @@ public class FsCourseLinkServiceImpl implements IFsCourseLinkService
                         return R.error("真实链接不存在").put("realLink", sLink);
                     }
                     log.info("链接仍然有效: {}", sLink);
-                    String json = configService.selectConfigByKey("h5.course.config");
+                    String json = configService.selectConfigByKey("course.config");
                     CourseConfig config = JSONUtil.toBean(json, CourseConfig.class);
                     String domainName = companyUserMapper.selectDomainByUserId(courseLink.getCompanyUserId());
                     if (StringUtils.isEmpty(domainName)){
                         domainName = config.getRealLinkDomainName();
                     }
                     String realLink = domainName+courseLink.getRealLink();
-                    String imgUrl = "";
+                    String imgUrl = cloudHostProper.getHeaderImg();
                     return R.ok().put("realLink",realLink ).put("config",config).put("headerImg",imgUrl);
                 }
             } else {

+ 7 - 4
fs-service-system/src/main/java/com/fs/course/service/impl/FsCourseQuestionBankServiceImpl.java

@@ -28,6 +28,7 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
+import javax.validation.constraints.Size;
 import java.util.*;
 import java.util.function.BiConsumer;
 import java.util.function.Function;
@@ -368,10 +369,11 @@ public class FsCourseQuestionBankServiceImpl implements IFsCourseQuestionBankSer
      *
      * @param list     数据
      * @param nickName 昵称
+     * @param userId
      * @return String
      */
     @Override
-    public String importData(List<FsCourseQuestionBankImportDTO> list, String nickName,Long userId) {
+    public String importData(List<FsCourseQuestionBankImportDTO> list, @Size String nickName, Long userId) {
         if (Objects.isNull(list) || list.isEmpty()) {
             throw new ServiceException("导入数据不能为空");
         }
@@ -390,8 +392,7 @@ public class FsCourseQuestionBankServiceImpl implements IFsCourseQuestionBankSer
                 }
 
                 // 构建题目对象
-                FsCourseQuestionBank questionBank = buildQuestionBank(importDTO, categoryData, nickName);
-                questionBank.setUserId(userId);
+                FsCourseQuestionBank questionBank = buildQuestionBank(importDTO, categoryData, nickName,userId);
                 importData.add(questionBank);
                 result.addSuccess(importDTO.getTitle());
 
@@ -408,6 +409,7 @@ public class FsCourseQuestionBankServiceImpl implements IFsCourseQuestionBankSer
         return result.buildResultMessage();
     }
 
+
     /**
      * 验证导入数据
      */
@@ -498,11 +500,12 @@ public class FsCourseQuestionBankServiceImpl implements IFsCourseQuestionBankSer
      */
     private FsCourseQuestionBank buildQuestionBank(FsCourseQuestionBankImportDTO importDTO,
                                                    Map<String, FsUserCourseCategory> categoryData,
-                                                   String nickName) {
+                                                   String nickName, Long userId) {
         FsCourseQuestionBank questionBank = new FsCourseQuestionBank();
 
         // 基础信息
         questionBank.setTitle(importDTO.getTitle());
+        questionBank.setUserId(userId);
         questionBank.setType(getQuestionTypeCode(importDTO.getType()));
         questionBank.setSort(importDTO.getSort());
         questionBank.setStatus(parseStatus(importDTO.getStatus()));

+ 24 - 9
fs-service-system/src/main/java/com/fs/course/service/impl/FsUserCourseServiceImpl.java

@@ -440,7 +440,7 @@ public class FsUserCourseServiceImpl implements IFsUserCourseService
 
     @Override
     public R createCourseSortLink(FsCourseLinkCreateParam param) {
-        String json = configService.selectConfigByKey("h5.course.config");
+        String json = configService.selectConfigByKey("course.config");
         CourseConfig config = JSONUtil.toBean(json, CourseConfig.class);
 
         //新增链接表信息
@@ -747,16 +747,31 @@ public class FsUserCourseServiceImpl implements IFsUserCourseService
     }
 
     private static Calendar getExpireDay(FsCourseLinkCreateParam param, CourseConfig config, Date createTime) {
-        Integer expireDuration;
-        if (param.getEffectiveDuration() == null || param.getEffectiveDuration() == 0){
-            expireDuration = config.getVideoLinkExpireDate();
-        }else {
-            expireDuration = param.getEffectiveDuration();
+        if (param == null || config == null || createTime == null) {
+            throw new IllegalArgumentException("Parameters cannot be null");
         }
-        // 设置过期时间
+
         Calendar calendar = Calendar.getInstance();
-        calendar.setTime(createTime);
-        calendar.add(Calendar.MINUTE, expireDuration);
+
+        if (param.getEffectiveDuration() == null || param.getEffectiveDuration() == 0) {
+            // 未传时间分钟的走配置,当天24:00(次日0:00)过期
+            Integer expireDays = config.getVideoLinkExpireDate() != null ? config.getVideoLinkExpireDate() : 1; // 默认1天
+
+            Date baseDate = param.getSendTime() != null ? param.getSendTime() : createTime;
+            calendar.setTime(baseDate);
+            calendar.add(Calendar.DAY_OF_MONTH, expireDays);
+
+            // 设置为次日0:00(即当天的24:00)
+            calendar.set(Calendar.HOUR_OF_DAY, 0);
+            calendar.set(Calendar.MINUTE, 0);
+            calendar.set(Calendar.SECOND, 0);
+            calendar.set(Calendar.MILLISECOND, 0);
+        } else {
+            // 传入时间分钟的
+            calendar.setTime(createTime);
+            calendar.add(Calendar.MINUTE, param.getEffectiveDuration());
+        }
+
         return calendar;
     }
 

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

@@ -1030,6 +1030,11 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
             fsCourseWatchLog.setLogType(1);
             fsCourseWatchLog.setProject(courseProject);
             courseWatchLogMapper.insertFsCourseWatchLog(fsCourseWatchLog);
+
+            String redisKey = "h5wxuser:watch:heartbeat:" + param.getUserId() + ":" + param.getVideoId() + ":" + param.getCompanyUserId();
+            redisCache.setCacheObject(redisKey, LocalDateTime.now().toString());
+            // 设置 Redis 记录的过期时间(例如 5 分钟)
+            redisCache.expire(redisKey, 300, TimeUnit.SECONDS);
         }
 
         // 添加会员销售关系表数据

+ 67 - 26
fs-service-system/src/main/java/com/fs/course/service/impl/FsUserWatchStatisticsServiceImpl.java

@@ -1,13 +1,16 @@
 package com.fs.course.service.impl;
 
 import java.math.BigDecimal;
-import java.util.Date;
-import java.util.List;
-import java.util.Map;
+import java.time.ZoneId;
+import java.time.ZonedDateTime;
+import java.util.*;
 import java.util.function.Function;
 import java.util.stream.Collectors;
 
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.fs.company.domain.Company;
+import com.fs.company.mapper.CompanyMapper;
+import com.fs.course.domain.FsUserCoursePeriod;
 import com.fs.course.mapper.FsUserCoursePeriodMapper;
 import com.fs.store.mapper.FsUserMapper;
 import com.google.common.collect.Lists;
@@ -15,6 +18,7 @@ import lombok.AllArgsConstructor;
 import org.apache.ibatis.session.ExecutorType;
 import org.apache.ibatis.session.SqlSession;
 import org.apache.ibatis.session.SqlSessionFactory;
+import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import com.fs.course.mapper.FsUserWatchStatisticsMapper;
@@ -39,6 +43,8 @@ public class FsUserWatchStatisticsServiceImpl extends ServiceImpl<FsUserWatchSta
     @Autowired
     private SqlSessionFactory sqlSessionFactory;
 
+    private final CompanyMapper companyMapper;
+
     /**
      * 查询会员看课统计-按营期统计
      *
@@ -115,33 +121,68 @@ public class FsUserWatchStatisticsServiceImpl extends ServiceImpl<FsUserWatchSta
     @Transactional
     public void insertStatistics() {
         // 1、获取统计结果
-        //获取会员数量和新增会员数量
-        List<FsUserWatchStatistics> userTotal = fsUserMapper.selectFsUserTotal();
-        FsUserWatchStatistics userTotalStatistics = new FsUserWatchStatistics();
-        if(!userTotal.isEmpty()){
-            userTotalStatistics = userTotal.get(0);
-        }
-
-        // 获取看课统计
+        // 获取所有的营期,并拆分公司id
+        FsUserCoursePeriod periodParam = new FsUserCoursePeriod();
+        List<FsUserCoursePeriod> fsUserCoursePeriods = fsUserCoursePeriodMapper.selectFsUserCoursePeriodList(periodParam);
+        Set<Long> companyIds = fsUserCoursePeriods.stream()
+                .flatMap(item -> Arrays.stream(item.getCompanyId().split(",")))
+                .map(Long::valueOf)
+                .collect(Collectors.toSet());
+
+        // 获取公司信息
+        List<Company> companies = companyMapper.selectCompanyByIds(companyIds);
+        Map<Long, Company> companyMap = companies.stream().collect(Collectors.toMap(Company::getCompanyId, Function.identity()));
+
+        // 获取看课统计(按营期按公司)
         List<FsUserWatchStatistics> courseWatchStatistics = baseMapper.getCourseWatchStatistics();
+        Map<String, FsUserWatchStatistics> courseWatchStatisticsMap = courseWatchStatistics.stream().collect(Collectors.toMap(k -> String.format("%s-%s", k.getPeriodId(), k.getCompanyId()), v -> v));
 
-//        // 转化map
-//        Map<Long, FsUserWatchStatistics> watchStatisticsMap = courseWatchStatistics.stream()
-//                .collect(Collectors.toMap(
-//                        FsUserWatchStatistics::getPeriodId,
-//                        Function.identity()
-//                ));
-        // 组装数据
-        for (FsUserWatchStatistics courseWatchStatistic : courseWatchStatistics) {
-            // 单独set,不用copy,避免copy出来的结果被前面的覆盖
-            courseWatchStatistic.setUserNum(userTotalStatistics.getUserNum() != null ? userTotalStatistics.getUserNum():0);
-            courseWatchStatistic.setNewUserNum(userTotalStatistics.getNewUserNum() != null ? userTotalStatistics.getNewUserNum():0);
-            courseWatchStatistic.setCreateTime(new Date());
-            courseWatchStatistic.setUpdateTime(new Date());
-        }
+        //获取公司的会员数量和今日新增会员数量
+        List<FsUserWatchStatistics> userTotal = fsUserMapper.selectFsUserTotal();
+        Map<String, FsUserWatchStatistics> userTotalMap = userTotal.stream().collect(Collectors.toMap(FsUserWatchStatistics::getCompanyId, Function.identity()));
+
+        List<FsUserWatchStatistics> list = fsUserCoursePeriods.stream()
+                .flatMap(item -> Arrays.stream(item.getCompanyId().split(","))
+                        .map(companyIdStr -> {
+                            Long companyId = Long.valueOf(companyIdStr.trim());
+                            Company company = companyMap.get(companyId);
+
+                            // 赋值
+                            FsUserWatchStatistics fsUserWatchStatistics = new FsUserWatchStatistics();
+                            BeanUtils.copyProperties(item, fsUserWatchStatistics);
+                            ZonedDateTime zonedDateTime = item.getPeriodStartingTime().atStartOfDay(ZoneId.systemDefault());
+                            fsUserWatchStatistics.setPeriodStartingTime(Date.from(zonedDateTime.toInstant()));
+                            fsUserWatchStatistics.setCompanyId(companyIdStr.trim());
+                            fsUserWatchStatistics.setCompanyName(company != null ? company.getCompanyName() : null);
+
+                            FsUserWatchStatistics userTotalData = userTotalMap.get(fsUserWatchStatistics.getCompanyId());
+
+                            String key = String.format("%s-%s", fsUserWatchStatistics.getPeriodId(), fsUserWatchStatistics.getCompanyId());
+                            FsUserWatchStatistics watchData = courseWatchStatisticsMap.get(key);
+
+                            if(userTotalData != null){
+                                fsUserWatchStatistics.setUserNum(userTotalData.getUserNum());
+                                fsUserWatchStatistics.setNewUserNum(userTotalData.getNewUserNum());
+                            } else {
+                                fsUserWatchStatistics.setUserNum(0);
+                                fsUserWatchStatistics.setNewUserNum(0);
+                            }
+
+                            if(watchData != null){
+                                fsUserWatchStatistics.setWatchNum(watchData.getWatchNum());
+                                fsUserWatchStatistics.setCompleteWatchNum(watchData.getCompleteWatchNum());
+                                fsUserWatchStatistics.setCompleteWatchRate(watchData.getCompleteWatchRate());
+                            } else {
+                                fsUserWatchStatistics.setWatchNum(0);
+                                fsUserWatchStatistics.setCompleteWatchNum(0);
+                                fsUserWatchStatistics.setCompleteWatchRate(BigDecimal.ZERO);
+                            }
+
+                            return fsUserWatchStatistics;
+                        })).collect(Collectors.toList());
 
         //2、分批次插入数据
-        this.batchInsert(courseWatchStatistics);
+        this.batchInsert(list);
     }
 
     private void batchInsert(List<FsUserWatchStatistics> list) {

+ 5 - 1
fs-service-system/src/main/java/com/fs/course/vo/FsUserWatchCourseStatisticsExportVO.java

@@ -83,9 +83,13 @@ public class FsUserWatchCourseStatisticsExportVO extends BaseEntity{
     private Integer completeWatchNum;
 
     /** 完播率 */
-    @Excel(name = "完播率")
+//    @Excel(name = "完播率")
     private BigDecimal completeWatchRate;
 
+    /** 完播率+% */
+    @Excel(name = "完播率")
+    private String completeWatchRatePercent;
+
     /** 红包领取数量 */
     @Excel(name = "红包领取个数")
     private Integer redPacketNum;

+ 10 - 6
fs-service-system/src/main/java/com/fs/crm/domain/CrmCustomer.java

@@ -1,16 +1,13 @@
 package com.fs.crm.domain;
 
-import java.math.BigDecimal;
-import java.util.Date;
 import com.fasterxml.jackson.annotation.JsonFormat;
 import com.fs.common.annotation.Excel;
 import com.fs.common.core.domain.BaseEntity;
 import lombok.Data;
-import org.apache.commons.lang3.builder.ToStringBuilder;
-import org.apache.commons.lang3.builder.ToStringStyle;
 
 import javax.validation.constraints.NotBlank;
-import javax.validation.constraints.Pattern;
+import java.math.BigDecimal;
+import java.util.Date;
 
 /**
  * 客户对象 crm_customer
@@ -177,5 +174,12 @@ public class CrmCustomer extends BaseEntity
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     private Date visitTime;
 
-
+    /**
+     * 客户级别
+     */
+    private Long customerLevel;
+    /**
+     * 是否置顶
+     */
+    private Integer isTop;
 }

+ 28 - 0
fs-service-system/src/main/java/com/fs/crm/domain/CrmCustomerLevel.java

@@ -0,0 +1,28 @@
+package com.fs.crm.domain;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+@TableName("crm_customer_level")
+@Data
+public class CrmCustomerLevel {
+    /**
+     * 主键ID
+     */
+    @TableId(type = IdType.AUTO)
+    private Long id;
+    /**
+     * 级别名称
+     */
+    private String name;
+    /**
+     * 状态 0显示 1停用
+     */
+    private Integer status;
+    /**
+     * 序号
+     */
+    private Integer sort;
+}

+ 18 - 0
fs-service-system/src/main/java/com/fs/crm/mapper/CrmCustomerLevelMapper.java

@@ -0,0 +1,18 @@
+package com.fs.crm.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.fs.crm.domain.CrmCustomerLevel;
+import com.fs.crm.param.CrmCustomerLevelQueryParam;
+import com.fs.crm.vo.CrmCustomerLevelVO;
+
+import java.util.List;
+
+public interface CrmCustomerLevelMapper extends BaseMapper<CrmCustomerLevel> {
+
+    /**
+     * 查询客户级别列表
+     * @param param 参数
+     * @return  list
+     */
+    List<CrmCustomerLevelVO> selectCrmCustomerLevelVOList(CrmCustomerLevelQueryParam param);
+}

+ 17 - 5
fs-service-system/src/main/java/com/fs/crm/mapper/CrmCustomerMapper.java

@@ -1,8 +1,5 @@
 package com.fs.crm.mapper;
 
-import java.util.List;
-import java.util.Map;
-
 import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.fs.crm.domain.CrmCustomer;
@@ -13,6 +10,9 @@ import org.apache.ibatis.annotations.Param;
 import org.apache.ibatis.annotations.Select;
 import org.apache.ibatis.annotations.Update;
 
+import java.util.List;
+import java.util.Map;
+
 /**
  * 客户Mapper接口
 
@@ -143,6 +143,9 @@ public interface CrmCustomerMapper extends BaseMapper<CrmCustomer>
             "<if test = 'maps.deptId != null  and maps.deptId != 0 '> " +
             "AND (c.dept_id = #{maps.deptId} OR c.dept_id IN ( SELECT t.dept_id FROM company_dept t WHERE find_in_set(#{maps.deptId}, ancestors) )) " +
             "</if>" +
+            "<if test = 'maps.customerLevel != null'> " +
+            "and c.customer_level =#{maps.customerLevel} " +
+            "</if>" +
             "${maps.params.dataScope}"+
             " order by c.customer_id desc "+
             "</script>"})
@@ -266,8 +269,11 @@ public interface CrmCustomerMapper extends BaseMapper<CrmCustomer>
             "<if test = 'maps.deptId != null  and maps.deptId != 0 '> " +
             "AND (c.dept_id = #{maps.deptId} OR c.dept_id IN ( SELECT t.dept_id FROM company_dept t WHERE find_in_set(#{maps.deptId}, ancestors) )) " +
             "</if>" +
+            "<if test = 'maps.customerLevel != null'> " +
+            "and c.customer_level = #{maps.customerLevel} " +
+            "</if>" +
             "${maps.params.dataScope}"+
-            " order by c.customer_id desc "+
+            " order by c.is_top desc, c.customer_id desc "+
             "</script>"})
     List<CrmCustomerListVO> selectCrmCustomerListQueryParam(@Param("maps")CrmCustomerListQueryParam crmCustomer);
 
@@ -412,7 +418,10 @@ public interface CrmCustomerMapper extends BaseMapper<CrmCustomer>
             "<if test = 'maps.endTime != null and maps.endTime != \"\" '> " +
             "and date_format(c.create_time,'%y%m%d') &lt;= date_format(#{maps.endTime},'%y%m%d') " +
             "</if>" +
-            " order by c.customer_id desc "+
+            "<if test = 'maps.customerLevel != null'> " +
+            "and c.customer_level =#{maps.customerLevel} " +
+            "</if>" +
+            " order by c.is_top desc,c.customer_id desc "+
             "</script>"})
     List<CrmLineCustomerListQueryVO> selectCrmLineCustomerListQuery(@Param("maps")CrmLineCustomerListQueryParam param);
 
@@ -620,4 +629,7 @@ public interface CrmCustomerMapper extends BaseMapper<CrmCustomer>
      * @return
      */
     List<Long> selectCustomerIdByCompanyUserId(@Param("companyUserId") Long companyUserId);
+
+    @Select("select *  from crm_customer where mobile=#{mobile} limit 1")
+    CrmCustomer selectFscrmByMobile(String mobile);
 }

+ 26 - 0
fs-service-system/src/main/java/com/fs/crm/param/CrmCustomerLevelParm.java

@@ -0,0 +1,26 @@
+package com.fs.crm.param;
+
+import lombok.Data;
+
+import javax.validation.constraints.NotBlank;
+
+@Data
+public class CrmCustomerLevelParm {
+    /**
+     * 主键ID
+     */
+    private Long id;
+    /**
+     * 级别名称
+     */
+    @NotBlank(message = "级别名称不能为空")
+    private String name;
+    /**
+     * 状态 0显示 1停用
+     */
+    private Integer status;
+    /**
+     * 序号
+     */
+    private Integer sort;
+}

+ 11 - 0
fs-service-system/src/main/java/com/fs/crm/param/CrmCustomerLevelQueryParam.java

@@ -0,0 +1,11 @@
+package com.fs.crm.param;
+
+import lombok.Data;
+
+@Data
+public class CrmCustomerLevelQueryParam {
+    /**
+     * 级别名称
+     */
+    private String name;
+}

+ 4 - 1
fs-service-system/src/main/java/com/fs/crm/param/CrmCustomerListQueryParam.java

@@ -2,7 +2,6 @@ package com.fs.crm.param;
 
 import com.fasterxml.jackson.annotation.JsonFormat;
 import com.fs.common.annotation.Excel;
-import com.fs.common.core.domain.BaseEntity;
 import com.fs.common.param.BaseQueryParam;
 import lombok.Data;
 
@@ -98,5 +97,9 @@ public class CrmCustomerListQueryParam extends BaseQueryParam
 
     private String[] receiveTimeList;
 
+    /**
+     * 客户级别
+     */
+    private Long customerLevel;
 
 }

+ 3 - 0
fs-service-system/src/main/java/com/fs/crm/param/CrmFullCustomerListQueryParam.java

@@ -87,4 +87,7 @@ public class CrmFullCustomerListQueryParam extends BaseQueryParam
 
     private Integer isPool;
 
+    /** 客户级别 */
+    private Long customerLevel;
+
 }

+ 2 - 0
fs-service-system/src/main/java/com/fs/crm/param/CrmLineCustomerListQueryParam.java

@@ -86,4 +86,6 @@ public class CrmLineCustomerListQueryParam extends BaseQueryParam
     @Excel(name = "标签" )
     private String tags;
 
+    /** 客户级别 */
+    private Long customerLevel;
 }

+ 3 - 0
fs-service-system/src/main/java/com/fs/crm/param/CrmMyCustomerListQueryParam.java

@@ -94,4 +94,7 @@ public class CrmMyCustomerListQueryParam extends BaseQueryParam
     private Integer isHisOrder;
     private String corpId;
 
+    /** 客户级别 */
+    private Long customerLevel;
+
 }

+ 3 - 0
fs-service-system/src/main/java/com/fs/crm/service/ICrmCustomerAssistService.java

@@ -4,6 +4,7 @@ import java.util.List;
 
 import com.fs.common.core.domain.R;
 import com.fs.crm.domain.CrmCustomerAssist;
+import com.fs.crm.domain.CrmCustomerContacts;
 import com.fs.crm.param.CrmCustomeAssignParam;
 import com.fs.crm.param.CrmCustomerAssistDeLParam;
 import com.fs.crm.param.CrmCustomerAssistOperationParam;
@@ -72,4 +73,6 @@ public interface ICrmCustomerAssistService
     List<CrmCustomerAssistVo> selectByCustomerIds(List<Long> customerIds);
 
     int allOperation(List<CrmCustomerAssistOperationParam> params,Long companyId,Long companyUserId);
+
+    List<CrmCustomerContacts> selectCrmCustomerContactsList(CrmCustomerContacts contactsMap);
 }

+ 40 - 0
fs-service-system/src/main/java/com/fs/crm/service/ICrmCustomerLevelService.java

@@ -0,0 +1,40 @@
+package com.fs.crm.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.fs.crm.domain.CrmCustomerLevel;
+import com.fs.crm.param.CrmCustomerLevelParm;
+import com.fs.crm.param.CrmCustomerLevelQueryParam;
+import com.fs.crm.vo.CrmCustomerLevelVO;
+
+import java.util.List;
+
+public interface ICrmCustomerLevelService extends IService<CrmCustomerLevel> {
+
+    /**
+     * 查询客户级别列表
+     * @param param 参数
+     * @return  list
+     */
+    List<CrmCustomerLevelVO> selectCrmCustomerLevelVOList(CrmCustomerLevelQueryParam param);
+
+    /**
+     * 新增客户级别
+     * @param param 参数
+     * @return 受影响行数
+     */
+    int saveCustomerLevel(CrmCustomerLevelParm param);
+
+    /**
+     * 修改客户级别
+     * @param param 参数
+     * @return 受影响行数
+     */
+    int editCustomerLevel(CrmCustomerLevelParm param);
+
+    /**
+     * 根据ID查询
+     * @param id id
+     * @return CrmCustomerLevelVO
+     */
+    CrmCustomerLevelVO selectCrmCustomerLevelVOById(Long id);
+}

+ 12 - 5
fs-service-system/src/main/java/com/fs/crm/service/ICrmCustomerService.java

@@ -1,16 +1,14 @@
 package com.fs.crm.service;
 
-import java.util.List;
-import java.util.Map;
-
 import com.alibaba.fastjson.JSONObject;
 import com.fs.common.core.domain.R;
 import com.fs.crm.domain.CrmCustomer;
 import com.fs.crm.param.*;
 import com.fs.crm.vo.*;
 import com.fs.qwApi.param.QwCustomerDetailParam;
-import com.fs.store.dto.StoreOrderExpressExportDTO;
-import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+import java.util.Map;
 
 /**
  * 客户Service接口
@@ -44,6 +42,7 @@ public interface ICrmCustomerService
      */
     public List<CrmCustomer> selectCrmCustomerList(CrmCustomer crmCustomer);
 
+    R assistToUser(String opeUserName, Long opeUserId, CrmCustomeAssignParam param);
     /**
      * 新增客户
      *
@@ -138,4 +137,12 @@ public interface ICrmCustomerService
     public List<CrmCustomerListVO> selectCrmCustomer1();
 
     List<CrmMyCustomerListQueryVO> selectCrmMyAssistListQuery(CrmMyCustomerListQueryParam param);
+
+    /**
+     * 置顶切换
+     * @param customerId 客户ID
+     */
+    void switchToTop(Long customerId);
+
+    CrmCustomer selectFscrmByMobile(String mobile);
 }

+ 9 - 8
fs-service-system/src/main/java/com/fs/crm/service/impl/CrmCustomerAssistServiceImpl.java

@@ -12,14 +12,10 @@ import com.fs.common.utils.DateUtils;
 import com.fs.common.utils.StringUtils;
 import com.fs.company.domain.CompanyUser;
 import com.fs.company.mapper.CompanyUserMapper;
-import com.fs.crm.domain.CrmCustomer;
-import com.fs.crm.domain.CrmCustomerLogs;
-import com.fs.crm.domain.CrmCustomerUser;
+import com.fs.crm.domain.*;
 import com.fs.crm.dto.CrmCustomerAssignUserDTO;
 import com.fs.crm.enums.CustomerLogEnum;
-import com.fs.crm.mapper.CrmCustomerLogsMapper;
-import com.fs.crm.mapper.CrmCustomerMapper;
-import com.fs.crm.mapper.CrmCustomerUserMapper;
+import com.fs.crm.mapper.*;
 import com.fs.crm.param.CrmCustomeAssignParam;
 import com.fs.crm.param.CrmCustomerAssistDeLParam;
 import com.fs.crm.param.CrmCustomerAssistOperationParam;
@@ -27,8 +23,6 @@ import com.fs.crm.vo.CrmCustomerAssistVo;
 import com.fs.jpush.service.JpushService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
-import com.fs.crm.mapper.CrmCustomerAssistMapper;
-import com.fs.crm.domain.CrmCustomerAssist;
 import com.fs.crm.service.ICrmCustomerAssistService;
 import org.springframework.transaction.annotation.Transactional;
 
@@ -44,6 +38,8 @@ public class CrmCustomerAssistServiceImpl implements ICrmCustomerAssistService
     @Autowired
     private CrmCustomerAssistMapper crmCustomerAssistMapper;
     @Autowired
+    private CrmCustomerContactsMapper crmCustomerContactsMapper;
+    @Autowired
     private CompanyUserMapper companyUserMapper;
     @Autowired
     private CrmCustomerMapper crmCustomerMapper;
@@ -312,4 +308,9 @@ public class CrmCustomerAssistServiceImpl implements ICrmCustomerAssistService
         });
         return count.get();
     }
+    @Override
+    public List<CrmCustomerContacts> selectCrmCustomerContactsList(CrmCustomerContacts crmCustomerContacts)
+    {
+        return crmCustomerContactsMapper.selectCrmCustomerContactsList(crmCustomerContacts);
+    }
 }

+ 102 - 0
fs-service-system/src/main/java/com/fs/crm/service/impl/CrmCustomerLevelServiceImpl.java

@@ -0,0 +1,102 @@
+package com.fs.crm.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.Wrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.fs.common.exception.CustomException;
+import com.fs.common.utils.bean.BeanUtils;
+import com.fs.crm.domain.CrmCustomerLevel;
+import com.fs.crm.mapper.CrmCustomerLevelMapper;
+import com.fs.crm.param.CrmCustomerLevelParm;
+import com.fs.crm.param.CrmCustomerLevelQueryParam;
+import com.fs.crm.service.ICrmCustomerLevelService;
+import com.fs.crm.vo.CrmCustomerLevelVO;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+import java.util.Objects;
+
+@Service
+public class CrmCustomerLevelServiceImpl extends ServiceImpl<CrmCustomerLevelMapper, CrmCustomerLevel> implements ICrmCustomerLevelService {
+
+    /**
+     * 查询客户级别列表
+     * @param param 参数
+     * @return  list
+     */
+    @Override
+    public List<CrmCustomerLevelVO> selectCrmCustomerLevelVOList(CrmCustomerLevelQueryParam param) {
+        return baseMapper.selectCrmCustomerLevelVOList(param);
+    }
+
+    /**
+     * 新增客户级别
+     * @param param 参数
+     * @return 受影响行数
+     */
+    @Override
+    public int saveCustomerLevel(CrmCustomerLevelParm param) {
+        CrmCustomerLevel crmCustomerLevel = getCustomerLevelByName(param.getName());
+        if (Objects.nonNull(crmCustomerLevel)) {
+            throw new CustomException("级别名称已存在");
+        }
+
+        crmCustomerLevel = new CrmCustomerLevel();
+        BeanUtils.copyProperties(param, crmCustomerLevel, "id");
+        return baseMapper.insert(crmCustomerLevel);
+    }
+
+    /**
+     * 根据名称查询客户级别
+     * @param name 名称
+     * @return CrmCustomerLevel
+     */
+    private CrmCustomerLevel getCustomerLevelByName(String name) {
+        Wrapper<CrmCustomerLevel> queryWrapper = Wrappers.<CrmCustomerLevel>lambdaQuery()
+                .eq(CrmCustomerLevel::getName, name)
+                .last("limit 1");
+        return getOne(queryWrapper);
+    }
+
+    /**
+     * 修改客户级别
+     * @param param 参数
+     * @return 受影响行数
+     */
+    @Override
+    public int editCustomerLevel(CrmCustomerLevelParm param) {
+        if (Objects.isNull(param.getId())) {
+            throw new CustomException("ID不能为空");
+        }
+
+        CrmCustomerLevel customerLevel = getById(param.getId());
+        if (Objects.isNull(customerLevel)) {
+            throw new CustomException("记录不存在");
+        }
+
+        CrmCustomerLevel levelByName = getCustomerLevelByName(param.getName());
+        if (Objects.nonNull(levelByName) && !levelByName.getId().equals(customerLevel.getId())) {
+            throw new CustomException("级别名称已存在");
+        }
+
+        BeanUtils.copyProperties(param, customerLevel, "id");
+        return baseMapper.updateById(customerLevel);
+    }
+
+    /**
+     * 根据ID查询
+     * @param id id
+     * @return CrmCustomerLevelVO
+     */
+    @Override
+    public CrmCustomerLevelVO selectCrmCustomerLevelVOById(Long id) {
+        CrmCustomerLevel customerLevel = getById(id);
+        if (Objects.isNull(customerLevel)) {
+            throw new CustomException("记录不存在");
+        }
+
+        CrmCustomerLevelVO crmCustomerLevelVO = new CrmCustomerLevelVO();
+        BeanUtils.copyProperties(customerLevel, crmCustomerLevelVO);
+        return crmCustomerLevelVO;
+    }
+}

+ 72 - 0
fs-service-system/src/main/java/com/fs/crm/service/impl/CrmCustomerServiceImpl.java

@@ -911,4 +911,76 @@ public class CrmCustomerServiceImpl extends ServiceImpl<CrmCustomerMapper, CrmCu
 
         return vos;
     }
+
+    /**
+     * 置顶切换
+     * @param customerId 客户ID
+     */
+    @Override
+    public void switchToTop(Long customerId) {
+        CrmCustomer crmCustomer = crmCustomerMapper.selectCrmCustomerById(customerId);
+        if (Objects.isNull(crmCustomer)){
+            throw new CustomException("客户不存在");
+        }
+
+        crmCustomer.setIsTop(crmCustomer.getIsTop() == 0 ? 1 : 0);
+        crmCustomerMapper.updateCrmCustomer(crmCustomer);
+    }
+
+    @Override
+    public CrmCustomer selectFscrmByMobile(String mobile){
+        return crmCustomerMapper.selectFscrmByMobile(mobile);
+    }
+
+    @Override
+    @Transactional
+    public R assistToUser(String opeUserName, Long opeUserId, CrmCustomeAssignParam param) {
+        Integer index=0;
+        for(CrmCustomerAssignUserDTO userDTO:param.getUsers()){
+            CompanyUser companyUser=companyUserMapper.selectCompanyUserById(userDTO.getCompanyUserId());
+            for(int i=0;i<userDTO.getCount();i++){
+                CrmCustomer customer=crmCustomerMapper.selectCrmCustomerById(param.getCustomerIds().get(index));
+                //不能选择客户拥有者本人
+                CrmCustomerUser crmCustomerUser = crmCustomerUserMapper.selectCrmCustomerUserById(customer.getCustomerUserId());
+                if (Objects.equals(crmCustomerUser.getCompanyUserId(), userDTO.getCompanyUserId())){
+                    return R.error("不能选择自己来协作!");
+                }
+                //查询协作客户
+                CrmCustomerAssist customerAssist=new CrmCustomerAssist();
+                customerAssist.setCustomerId(customer.getCustomerId());
+                customerAssist.setCompanyUserId(userDTO.getCompanyUserId());
+                List<CrmCustomerAssist> tempList = assistMapper.selectCrmCustomerAssistList(customerAssist);
+                if(tempList!=null && !tempList.isEmpty()){
+                    return R.error("销售:" + companyUser.getNickName() +"(" + userDTO.getCompanyUserId() + ")已拥有改该协作客户:" + customer.getCustomerName());
+                }
+                customerAssist.setCompanyId(param.getCompanyId());
+                customerAssist.setCompanyUserName(companyUser.getNickName());
+                customerAssist.setCreateTime(new Date());
+                assistMapper.insertCrmCustomerAssist(customerAssist);
+                //写日志
+                CrmCustomerLogs logs=new CrmCustomerLogs();
+                logs.setCustomerId(customer.getCustomerId());
+                logs.setCreateTime(new Date());
+                logs.setLogsType(CustomerLogEnum.ASSIST_USER.getValue());
+                logs.setTitle(CustomerLogEnum.ASSIST_USER.getDesc());
+                logs.setRemark(opeUserName+"为客户"+customer.getCustomerName()+"添加协作人:" + companyUser.getNickName());
+                logs.setCompanyUserId(userDTO.getCompanyUserId());
+                logsMapper.insertCrmCustomerLogs(logs);
+
+                if(StringUtils.isNotEmpty(companyUser.getJpushId())){
+                    Map<String, String> extrasMap=new HashMap<>();
+                    extrasMap.put("customerId",customer.getCustomerId().toString());
+                    extrasMap.put("type","1");
+                    try {
+                        jpushService.sendRegisterIdPush("客户消息","您收到 一个客户协作邀请",extrasMap,companyUser.getJpushId());
+                    } catch (APIConnectionException e) {
+                    } catch (APIRequestException e) {
+                    }
+                }
+                index++;
+            }
+        }
+        return R.ok();
+    }
+
 }

+ 23 - 0
fs-service-system/src/main/java/com/fs/crm/vo/CrmCustomerLevelVO.java

@@ -0,0 +1,23 @@
+package com.fs.crm.vo;
+
+import lombok.Data;
+
+@Data
+public class CrmCustomerLevelVO {
+    /**
+     * 主键ID
+     */
+    private Long id;
+    /**
+     * 级别名称
+     */
+    private String name;
+    /**
+     * 状态 0显示 1停用
+     */
+    private Integer status;
+    /**
+     * 序号
+     */
+    private Integer sort;
+}

+ 5 - 0
fs-service-system/src/main/java/com/fs/crm/vo/CrmCustomerListVO.java

@@ -127,4 +127,9 @@ public class CrmCustomerListVO implements Serializable
     @Excel(name = "进线客户提交日期" )
     private String registerSubmitTime;
 
+    /** 客户级别 */
+    private Long customerLevel;
+    /** 置顶状态 0未置顶 1置顶 */
+    private Integer isTop;
+
 }

+ 3 - 0
fs-service-system/src/main/java/com/fs/crm/vo/CrmFullCustomerListQueryVO.java

@@ -101,4 +101,7 @@ public class CrmFullCustomerListQueryVO implements Serializable
     private String sourceCode;
     private String pushTime;
     private String pushCode;
+
+    /** 客户级别 */
+    private Long customerLevel;
 }

+ 4 - 0
fs-service-system/src/main/java/com/fs/crm/vo/CrmLineCustomerListQueryVO.java

@@ -106,5 +106,9 @@ public class CrmLineCustomerListQueryVO implements Serializable
     /** 非重客户Id(重客户最早录入手机号码的客户id) */
     private Long dCustomerId;
 
+    /** 客户级别 */
+    private Long customerLevel;
+    /** 是否置顶 0未置顶 1置顶 */
+    private Integer isTop;
 
 }

+ 3 - 0
fs-service-system/src/main/java/com/fs/crm/vo/CrmMyCustomerListQueryVO.java

@@ -123,4 +123,7 @@ public class CrmMyCustomerListQueryVO implements Serializable
     private List<String> assistUser;
     private Long companyUserId;
 
+    /** 客户级别 */
+    private Long customerLevel;
+
 }

+ 5 - 1
fs-service-system/src/main/java/com/fs/statis/service/impl/StatisticsCompanyServiceImpl.java

@@ -949,7 +949,11 @@ public class StatisticsCompanyServiceImpl implements IStatisticsCompanyService {
 
     @Override
     public List<WatchEndPlayTrendDTO> watchEndPlayTrend(AnalysisPreviewQueryDTO param) {
-        return Collections.emptyList();
+        List<WatchEndPlayTrendDTO> watchEndPlayTrendDTOS = consumptionBalanceMapper.watchEndPlayTrend(param);
+        for (WatchEndPlayTrendDTO watchEndPlayTrendDTO : watchEndPlayTrendDTOS) {
+            watchEndPlayTrendDTO.setX(watchEndPlayTrendDTO.getStartDate());
+        }
+        return watchEndPlayTrendDTOS;
     }
 
     @Override

+ 10 - 5
fs-service-system/src/main/java/com/fs/store/mapper/FsStoreOrderMapper.java

@@ -1,5 +1,6 @@
 package com.fs.store.mapper;
 
+import java.math.BigDecimal;
 import java.util.Date;
 import java.util.List;
 import java.util.Map;
@@ -13,10 +14,7 @@ import com.fs.statis.domain.Report;
 import com.fs.statis.param.ReportParam;
 import com.fs.store.domain.FsStoreOrder;
 import com.fs.store.domain.FsStoreOrderItem;
-import com.fs.store.param.FsCustomerStoreOrderListQueryParam;
-import com.fs.store.param.FsMyStoreOrderQueryParam;
-import com.fs.store.param.FsStoreOrderParam;
-import com.fs.store.param.FsStoreStatisticsParam;
+import com.fs.store.param.*;
 import com.fs.store.vo.*;
 import org.apache.ibatis.annotations.Param;
 import org.apache.ibatis.annotations.Select;
@@ -163,7 +161,9 @@ public interface FsStoreOrderMapper
             " AND date_format(o.delivery_send_time,'%y%m%d') &gt;= date_format(#{maps.deliverySendTimeList[0]},'%y%m%d') " +
             " AND date_format(o.delivery_send_time,'%y%m%d') &lt;= date_format(#{maps.deliverySendTimeList[1]},'%y%m%d') " +
             "</if>" +
-
+            "<if test = 'maps.paid != null    '> " +
+            "and o.paid =#{maps.paid} " +
+            "</if>" +
             "<if test = 'maps.payTimeList != null    '> " +
             " AND date_format(o.pay_time,'%y%m%d') &gt;= date_format(#{maps.payTimeList[0]},'%y%m%d') " +
             " AND date_format(o.pay_time,'%y%m%d') &lt;= date_format(#{maps.payTimeList[1]},'%y%m%d') " +
@@ -524,6 +524,7 @@ public interface FsStoreOrderMapper
             "where o.user_id=#{userId}  and o.status =#{status} " +
             "</script>"})
     int selectFsStoreOrderCount(@Param("userId")long userId,@Param("status")int status);
+
     @Select({"<script> " +
             "select * from fs_store_order o  " +
             "where o.delivery_id=#{deliveryId}  limit 1 " +
@@ -1044,4 +1045,8 @@ public interface FsStoreOrderMapper
     List<Long> selectFsStoreOrderNoCreateOmsAndReviewed();
 
     List<Report> selectOrderByCustomerIds(@Param("map") ReportParam param);
+
+    int selectFsStoreOrderCount(FsStoreOrderStatisticsParam param);
+
+    BigDecimal selectFsStoreOrderByPayPriceCount(FsStoreOrderStatisticsParam param);
 }

+ 11 - 9
fs-service-system/src/main/java/com/fs/store/mapper/FsUserMapper.java

@@ -217,7 +217,7 @@ public interface FsUserMapper
     List<FsUserPageListVO> selectFsUserPageListNew(FsUserPageListParam param);
     Long selectFsUserPageListCount(FsUserPageListParam param);
 
-    List<UserListCountVO> getUserNumber(@Param("userId") Long userId);
+    List<UserListCountVO> getUserNumber(@Param("userId") Long userId, @Param("companyId") Long companyId);
 
     int getRepeatUserNumber(@Param("userId") Long userId);
 
@@ -246,9 +246,9 @@ public interface FsUserMapper
 
     void transferCompanyUser(FsUserTransferParamDTO param);
 
-    FsUserSummaryCountVO countUserSummary(@Param("userId") Long userId);
+    FsUserSummaryCountVO countUserSummary(@Param("userId") Long userId, @Param("companyId") Long companyId);
 
-    List<FsUserSummaryCountTagVO> countTag(@Param("userId") Long userId);
+    List<FsUserSummaryCountTagVO> countTag(@Param("userId") Long userId, @Param("companyId") Long companyId);
 
     Map<String, Long> countUserCourse(UserStatisticsCommonParam param);
 
@@ -258,13 +258,13 @@ public interface FsUserMapper
 
     Map<String, Long> countCourseDetails(UserStatisticsCommonParam param);
 
-    List<FsUserRankingVO> countUserRankingByComplete(@Param("userId") Long userId, @Param("startTime") String startTime, @Param("endTime") String endTime, @Param("periodId")String periodId, @Param("videoId")String videoId, @Param("order")String order);
+    List<FsUserRankingVO> countUserRankingByComplete(@Param("userId") Long userId, @Param("companyId") Long companyId, @Param("startTime") String startTime, @Param("endTime") String endTime, @Param("periodId")String periodId, @Param("videoId")String videoId, @Param("order")String order);
 
-    List<FsUserRankingVO> countUserRankingByRight(@Param("userId") Long userId, @Param("startTime") String startTime, @Param("endTime") String endTime, @Param("periodId")String periodId, @Param("videoId")String videoId, @Param("order")String order);
+    List<FsUserRankingVO> countUserRankingByRight(@Param("userId") Long userId, @Param("companyId") Long companyId, @Param("startTime") String startTime, @Param("endTime") String endTime, @Param("periodId")String periodId, @Param("videoId")String videoId, @Param("order")String order);
 
-    List<FsCourseRankingVO> countCourseRankingByComplete(@Param("userId") Long userId, @Param("startTime") String startTime, @Param("endTime") String endTime, @Param("periodId")String periodId, @Param("videoId")String videoId, @Param("order")String order);
+    List<FsCourseRankingVO> countCourseRankingByComplete(@Param("userId") Long userId, @Param("companyId") Long companyId, @Param("startTime") String startTime, @Param("endTime") String endTime, @Param("periodId")String periodId, @Param("videoId")String videoId, @Param("order")String order);
 
-    List<FsCourseRankingVO> countCourseRankingByRight(@Param("userId") Long userId, @Param("startTime") String startTime, @Param("endTime") String endTime, @Param("periodId")String periodId, @Param("videoId")String videoId, @Param("order")String order);
+    List<FsCourseRankingVO> countCourseRankingByRight(@Param("userId") Long userId, @Param("companyId") Long companyId, @Param("startTime") String startTime, @Param("endTime") String endTime, @Param("periodId")String periodId, @Param("videoId")String videoId, @Param("order")String order);
 
     List<FsCourseAnalysisCountVO> courseAnalysisCourseCount(CourseAnalysisParam param);
 
@@ -272,9 +272,9 @@ public interface FsUserMapper
 
     List<FsCourseAnalysisCountVO> courseAnalysisAnswerCount(CourseAnalysisParam param);
 
-    CompanyUserSummaryCountVO companyUserCount(@Param("companyUserId")String companyUserId);
+    CompanyUserSummaryCountVO companyUserCount(@Param("companyUserId")String companyUserId, @Param("companyId") Long companyId);
 
-    CompanyUserSummaryCountVO newUserRedPacketCount(@Param("companyUserId")String companyUserId);
+    CompanyUserSummaryCountVO newUserRedPacketCount(@Param("companyUserId")String companyUserId, @Param("companyId") Long companyId);
 
     List<FsUser> getFsUserByCompanyUserAndId(@Param("companyUserId")Long companyUserId, @Param("userId") Long userId);
 
@@ -287,6 +287,8 @@ public interface FsUserMapper
 
     int batchUpdateUserCompanyUser(@Param("userIds") List<Long> userIds, @Param("companyUserId") Long companyUserId, @Param("companyId") Long companyId);
 
+    int batchUpdateCompanyUserRelation(@Param("userIds") List<Long> userIds, @Param("companyUserId") Long companyUserId, @Param("companyId") Long companyId);
+
     /**
      * 查询会员选项列表
      * @param params    参数

+ 5 - 0
fs-service-system/src/main/java/com/fs/store/param/FsStoreOrderParam.java

@@ -82,4 +82,9 @@ public class FsStoreOrderParam extends BaseEntity implements Serializable
 
     private String orderVisit;
 
+    /**
+     * 支付状态 待支付 1已支付
+     */
+    private int paid;
+
 }

+ 26 - 0
fs-service-system/src/main/java/com/fs/store/param/FsStoreOrderStatisticsParam.java

@@ -0,0 +1,26 @@
+package com.fs.store.param;
+
+import lombok.Data;
+
+@Data
+public class FsStoreOrderStatisticsParam {
+
+    /**
+     * 开始时间
+     */
+    String startTime;
+    /**
+     * 结束时间
+     */
+    String endTime;
+
+    /**
+     * 是否已经支付
+     */
+    Integer paid;
+
+    /**
+     * 订单状态(-1 : 申请退款 -2 : 退货成功 1:待支付 2:待发货;3:待收货;4:待评价;5:已完成)
+     */
+    private Integer status;
+}

+ 15 - 0
fs-service-system/src/main/java/com/fs/store/service/IFsStoreOrderService.java

@@ -125,6 +125,13 @@ public interface IFsStoreOrderService
 
     Integer selectFsStoreOrderCount(long userId, int status);
 
+    /**
+     * 根据时间查询订单总数
+     * @param param
+     * @return
+     */
+    Integer selectFsStoreOrderCount(FsStoreOrderStatisticsParam param);
+
     R computedPackageOrder(long userId, FsStoreComputedPackageIdOrderParam param);
 
     FsStoreOrder selectFsStoreOrderByDeliveryId(String logisticCode);
@@ -211,4 +218,12 @@ public interface IFsStoreOrderService
      * @return R
      */
     R finishStoreOrder(Long orderId);
+
+    /**
+     * 根据时间查询实际支付金额
+     *
+     * @param param
+     * @return
+     */
+    BigDecimal selectFsStoreOrderByPayPriceCount(FsStoreOrderStatisticsParam param);
 }

+ 10 - 0
fs-service-system/src/main/java/com/fs/store/service/impl/FsStoreOrderServiceImpl.java

@@ -1327,6 +1327,11 @@ public class FsStoreOrderServiceImpl implements IFsStoreOrderService
         }
     }
 
+    @Override
+    public BigDecimal selectFsStoreOrderByPayPriceCount(FsStoreOrderStatisticsParam param) {
+        return fsStoreOrderMapper.selectFsStoreOrderByPayPriceCount(param);
+    }
+
     @Override
     @Transactional
     //类型1支付回调 类型2货到付款
@@ -2174,6 +2179,11 @@ public class FsStoreOrderServiceImpl implements IFsStoreOrderService
         return fsStoreOrderMapper.selectFsStoreOrderCount(userId,status);
     }
 
+    @Override
+    public Integer selectFsStoreOrderCount(FsStoreOrderStatisticsParam param) {
+        return fsStoreOrderMapper.selectFsStoreOrderCount(param);
+    }
+
     @Override
     public R computedPackageOrder(long userId, FsStoreComputedPackageIdOrderParam param) {
         FsStoreProductPackage storeProductPackage=productPackageService.selectFsStoreProductPackageById(param.getPackageId());

+ 63 - 9
fs-service-system/src/main/java/com/fs/store/service/impl/FsUserServiceImpl.java

@@ -55,6 +55,7 @@ import com.fs.store.vo.FSUserVO;
 import com.fs.store.vo.FsCompanyUserListQueryVO;
 import com.fs.store.vo.FsUserTuiVO;
 import com.fs.store.vo.h5.*;
+import com.github.pagehelper.PageHelper;
 import com.github.pagehelper.PageInfo;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.collections4.CollectionUtils;
@@ -474,6 +475,9 @@ public class FsUserServiceImpl implements IFsUserService
             param.setUserId(0L);
             param.setCompanyId(companyUser.getCompanyId());
         }
+
+        PageHelper.startPage(param.getPageNum(), param.getPageSize());
+
         List<FsUserPageListVO> fsUserPageListVOS = fsUserMapper.selectFsUserPageList(param);
 
         // 获取当前销售所有重粉会员
@@ -596,7 +600,14 @@ public class FsUserServiceImpl implements IFsUserService
 
     @Override
     public UserListPageVO getUserNumber(Long userId) {
-        List<UserListCountVO> list = fsUserMapper.getUserNumber(userId);
+        // 判断是否是管理员
+        Long companyId = null;
+        CompanyUser companyUser = companyUserMapper.selectCompanyUserById(userId);
+        if (companyUser != null && companyUser.isAdmin()){
+            userId = 0L;
+            companyId = companyUser.getCompanyId();
+        }
+        List<UserListCountVO> list = fsUserMapper.getUserNumber(userId, companyId);
         Map<String, Integer> map = list.stream()
                 .collect(Collectors.toMap(UserListCountVO::getStatus, UserListCountVO::getNum, (v1, v2) -> v1));
         UserListPageVO pageVO = new UserListPageVO();
@@ -672,8 +683,15 @@ public class FsUserServiceImpl implements IFsUserService
 
     @Override
     public FsUserSummaryCountVO userSummaryCount(Long userId) {
-        FsUserSummaryCountVO fsUserSummaryCountVO = fsUserMapper.countUserSummary(userId);
-        List<FsUserSummaryCountTagVO> countTagList = fsUserMapper.countTag(userId);
+        // 判断是否是管理员
+        Long companyId = null;
+        CompanyUser companyUser = companyUserMapper.selectCompanyUserById(userId);
+        if (companyUser != null && companyUser.isAdmin()){
+            userId = 0L;
+            companyId = companyUser.getCompanyId();
+        }
+        FsUserSummaryCountVO fsUserSummaryCountVO = fsUserMapper.countUserSummary(userId, companyId);
+        List<FsUserSummaryCountTagVO> countTagList = fsUserMapper.countTag(userId, companyId);
         fsUserSummaryCountVO.setTagList(countTagList);
         return fsUserSummaryCountVO;
     }
@@ -686,6 +704,12 @@ public class FsUserServiceImpl implements IFsUserService
     private FsUserStatisticsVO getUserStatistics(UserStatisticsCommonParam param) {
         FsUserStatisticsVO fsUserStatisticsVO = new FsUserStatisticsVO();
 
+        // 判断是否是管理员
+        CompanyUser companyUser = companyUserMapper.selectCompanyUserById(param.getUserId());
+        if (companyUser != null && companyUser.isAdmin()){
+            param.setUserId(0L);
+            param.setCompanyId(companyUser.getCompanyId());
+        }
         // 获取课程统计
         Map<String, Long> couserMap = fsUserMapper.countUserCourse(param);
         if (couserMap != null) {
@@ -727,6 +751,11 @@ public class FsUserServiceImpl implements IFsUserService
     public FsUserStatisticsVO userStatisticsDetails(UserStatisticsCommonParam param) {
         FsUserStatisticsVO userStatisticsVO = getUserStatistics(param);
 
+        // 判断是否是管理员
+        CompanyUser companyUser = companyUserMapper.selectCompanyUserById(param.getUserId());
+        if (companyUser != null && companyUser.isAdmin()){
+            param.setUserId(0L);
+        }
         //统计课程数据详情,在查询统计详情的时候需要显示
         Map<String, Long> courseDetailsMap = fsUserMapper.countCourseDetails(param);
         if(courseDetailsMap != null && courseDetailsMap.get("courseNum") != null && courseDetailsMap.get("videoNum") != null && courseDetailsMap.get("courseUserNum") != null){
@@ -740,25 +769,39 @@ public class FsUserServiceImpl implements IFsUserService
     @Override
     public List<FsUserRankingVO> userRanking(Long userId, String startTime, String endTime, String periodId, String videoId, String order, Integer type) {
         List<FsUserRankingVO> listVO = Collections.emptyList();
+        // 判断是否是管理员
+        Long companyId = null;
+        CompanyUser companyUser = companyUserMapper.selectCompanyUserById(userId);
+        if (companyUser != null && companyUser.isAdmin()){
+            userId = 0L;
+            companyId = companyUser.getCompanyId();
+        }
         if(type == 1){
             //按完播率
-            listVO = fsUserMapper.countUserRankingByComplete(userId, startTime, endTime, periodId, videoId, order);
+            listVO = fsUserMapper.countUserRankingByComplete(userId, companyId, startTime, endTime, periodId, videoId, order);
         }
         if(type == 2){
             //按正确率
-            listVO = fsUserMapper.countUserRankingByRight(userId, startTime, endTime, periodId, videoId, order);
+            listVO = fsUserMapper.countUserRankingByRight(userId, companyId, startTime, endTime, periodId, videoId, order);
         }
         return listVO;
     }
 
     @Override
     public List<FsCourseRankingVO> courseRanking(Long userId, String startTime, String endTime, String periodId, String videoId, String order, Integer type) {
+        // 判断是否是管理员
+        Long companyId = null;
+        CompanyUser companyUser = companyUserMapper.selectCompanyUserById(userId);
+        if (companyUser != null && companyUser.isAdmin()){
+            userId = 0L;
+            companyId = companyUser.getCompanyId();
+        }
         List<FsCourseRankingVO> list = Collections.emptyList();
         if(type == 1){
-            list = fsUserMapper.countCourseRankingByComplete(userId, startTime, endTime, periodId, videoId, order);
+            list = fsUserMapper.countCourseRankingByComplete(userId, companyId, startTime, endTime, periodId, videoId, order);
         }
         if(type == 2){
-            list = fsUserMapper.countCourseRankingByRight(userId, startTime, endTime, periodId, videoId, order);
+            list = fsUserMapper.countCourseRankingByRight(userId, companyId, startTime, endTime, periodId, videoId, order);
         }
 
         return list;
@@ -830,8 +873,15 @@ public class FsUserServiceImpl implements IFsUserService
 
     @Override
     public CompanyUserSummaryCountVO companyUserSummaryCount(Long userId, String companyUserId) {
-        CompanyUserSummaryCountVO companyUserCount = fsUserMapper.companyUserCount(companyUserId);
-        CompanyUserSummaryCountVO newUserRedPacketCount = fsUserMapper.newUserRedPacketCount(companyUserId);
+        // 判断是否是管理员
+        Long companyId = null;
+        CompanyUser companyUser = companyUserMapper.selectCompanyUserById(userId);
+        if (companyUser != null && companyUser.isAdmin()){
+            companyUserId = String.valueOf(0);
+            companyId = companyUser.getCompanyId();
+        }
+        CompanyUserSummaryCountVO companyUserCount = fsUserMapper.companyUserCount(companyUserId, companyId);
+        CompanyUserSummaryCountVO newUserRedPacketCount = fsUserMapper.newUserRedPacketCount(companyUserId, companyId);
         CompanyUserSummaryCountVO vo = new CompanyUserSummaryCountVO();
         BeanUtils.copyProperties(companyUserCount, vo);
         vo.setUserRedPacketNum(newUserRedPacketCount.getUserRedPacketNum());
@@ -858,6 +908,10 @@ public class FsUserServiceImpl implements IFsUserService
         if (Objects.isNull(companyUser)){
             return ResponseResult.fail(405,"销售不存在");
         }
+        // 通过字段值判断该销售是否允许注册会员
+        if(companyUser.getIsAllowedAllRegister() != null && companyUser.getIsAllowedAllRegister() == 0){
+            return ResponseResult.fail(407,"不允许注册会员,请联系管理员");
+        }
 
         // 添加关系表数据
         FsUserCompanyUser fsUserCompanyUser = getFsUserCompanyUser(param, fsUser);

+ 8 - 0
fs-service-system/src/main/java/com/fs/wx/pay/config/WxPayProperties.java

@@ -40,4 +40,12 @@ public class WxPayProperties {
 
   private String notifyUrl;
 
+  private String privateKeyPath;
+
+  private String privateCertPath;
+
+  private String certSerialNo;
+
+  private String nativeNotifyUrl;
+
 }

+ 5 - 0
fs-service-system/src/main/resources/application-config-bly.yml

@@ -62,6 +62,11 @@ wx:
         token: Ncbnd7lJvkripVOpyTFAna6NAWCxCrvC
         aesKey: HlEiBB55eaWUaeBVAQO3cWKWPYv1vOVQSq7nFNICw4E
         msgDataFormat: JSON
+      - appid: wx301ab2fad04c658a   #倍力优看课小程序
+        secret: 35018f10929b84c8c4a225de253bbcc6
+        token: Ncbnd7lJvkripVOpyTFAna6NAWCxCrvC
+        aesKey: HlEiBB55eaWUaeBVAQO3cWKWPYv1vOVQSq7nFNICw4E
+        msgDataFormat: JSON
 
   pay:
     appId: wx11a2ce7c2bbc4521 #微信公众号或者小程序等的appid

+ 2 - 0
fs-service-system/src/main/resources/application-config-dev.yml

@@ -120,3 +120,5 @@ tencent_cloud_config:
   proxy: hylj
 cloud_host:
   company_name: 润天
+headerImg:
+  imgUrl: https://zkzh-2025.oss-cn-beijing.aliyuncs.com/fs/20250619/e31b5e051a474a7a9b4ad02575b46196.png

+ 10 - 5
fs-service-system/src/main/resources/application-config-fby.yml

@@ -84,14 +84,17 @@ wx:
         msgDataFormat: JSON
 
   pay:
-    appId: wx11a2ce7c2bbc4521 #微信公众号或者小程序等的appid
-    mchId: 1703311381 #微信支付商户号
-    mchKey: FotTIbIzn4AisMW7de712LJQIazSqqAl #微信支付商户密钥
-    v3Key: y5Eo99q93qzdQRAs6E2BDKIF7f3EnS3G
+    appId: wx961fadab9bcb792b #微信公众号或者小程序等的appid
+    mchId: 1716217886 #微信支付商户号
+    mchKey: a7Fc5B9dE2h8J3kL4mN6pQ7rS9tU2vW1 #微信支付商户密钥
     subAppId:  #服务商模式下的子商户公众账号ID
     subMchId:  #服务商模式下的子商户号
     keyPath: c:\\Tools\\cert\\apiclient_cert.p12 # p12证书的位置,可以指定绝对路径,也可以指定类路径(以classpath:开头)
     notifyUrl:  https://userapp.bly.ylrztop.com/app/wxpay/wxPayNotify
+    privateKeyPath: 'C:\cert\1716217886_20250509_cert\apiclient_key.pem'
+    privateCertPath: 'C:\cert\1716217886_20250509_cert\apiclient_cert.pem'
+    certSerialNo: '4E8BD68BC2BFD37CA58244D660E5FDCCE475D82E'
+    nativeNotifyUrl: 'http://company.fbylive.com/prod-api/pay/wxPay/payNotify'
   mp:
     useRedis: false
     redisConfig:
@@ -100,7 +103,7 @@ wx:
       timeout: 2000
     configs:
       - appId: wx961fadab9bcb792b # 第一个公众号的appid  //公众号名称:云联
-        secret: eddde2a1d4ca0c6c443a67e542b6864c
+        secret: 8adb2a7533921449ef6e60814c2ff075
         token: PPKOdAlCoMO # 接口配置里的Token值
         aesKey: Eswa6VjwtVMCcw03qZy6fWllgrv5aytIA1SZPEU0kU2 # 接口配置里的EncodingAESKey值
 jpush:
@@ -120,3 +123,5 @@ tencent_cloud_config:
   proxy: fby
 cloud_host:
   company_name: 福本源
+headerImg:
+  imgUrl:

+ 2 - 0
fs-service-system/src/main/resources/application-config-zkzh.yml

@@ -113,3 +113,5 @@ tencent_cloud_config:
   proxy: zkzh
 cloud_host:
   company_name: 中康
+headerImg:
+  imgUrl: https://zkzh-2025.oss-cn-beijing.aliyuncs.com/fs/20250619/e31b5e051a474a7a9b4ad02575b46196.png

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

@@ -1,5 +1,7 @@
 # 数据源配置
 spring:
+    profiles:
+        include: config-dev,common
     # redis 配置
     redis:
         # 地址

+ 2 - 0
fs-service-system/src/main/resources/application-druid-bly.yml

@@ -1,5 +1,7 @@
 # 数据源配置
 spring:
+    profiles:
+        include: config-bly,common
     # redis 配置
     redis:
         # 地址

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

@@ -1,5 +1,7 @@
 # 数据源配置
 spring:
+  profiles:
+    include: common,config-fby
   # redis 配置
   redis:
     # 地址

+ 14 - 0
fs-service-system/src/main/resources/db/upgrade/20250621客户分级.sql

@@ -0,0 +1,14 @@
+-- 客户级别表
+drop table if exists crm_customer_level;
+create table crm_customer_level (
+    `id`        bigint          not null auto_increment comment '主键ID',
+    `name`      varchar(255)    not null                comment '级别名称',
+    `status`    tinyint         default 0               comment '状态 0显示 1停用',
+    `sort`      int             default 0               comment '序号',
+    primary key (`id`) using btree
+) engine = InnoDB comment = '客户级别表';
+
+-- 客户表新增级别字段、置顶字段
+alter table crm_customer
+    add column `customer_level` bigint comment '客户级别' after `customer_type`,
+    add column `is_top` tinyint default 0 comment '是否置顶 0未置顶 1置顶';

+ 8 - 0
fs-service-system/src/main/resources/mapper/company/CompanyMapper.xml

@@ -163,4 +163,12 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         </foreach>
     </delete>
 
+    <select id="selectCompanyByIds" parameterType="Long" resultType="Company">
+        <include refid="selectCompanyVo"/>
+        where company_id in
+        <foreach item="companyId" collection="companyIds" open="(" separator="," close=")">
+            #{companyId}
+        </foreach>
+    </select>
+
 </mapper>

+ 10 - 1
fs-service-system/src/main/resources/mapper/company/CompanyUserMapper.xml

@@ -40,6 +40,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         <result property="isAudit"    column="is_audit"    />
         <result property="addressId"    column="address_id"    />
         <result property="isNeedRegisterMember"    column="is_need_register_member"    />
+        <result property="isAllowedAllRegister"    column="is_allowed_all_register"    />
         <association property="dept"    column="dept_id" javaType="CompanyDept" resultMap="deptResult" />
         <collection  property="roles"   javaType="java.util.List"        resultMap="RoleResult" />
 
@@ -277,7 +278,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         select u.user_id,u.company_id,u.qw_user_id, u.dept_id, u.user_name, u.nick_name, u.email, u.avatar, u.phonenumber, u.password, u.sex, u.status, u.del_flag, u.login_ip, u.login_date, u.create_by, u.create_time,u.id_card, u.remark,u.user_type,u.open_id,u.qr_code_weixin,u.qr_code_wecom,u.jpush_id,u.domain,u.is_audit,u.address_id,
         d.dept_id, d.parent_id, d.dept_name, d.order_num, d.leader, d.status as dept_status,
         r.role_id, r.role_name, r.role_key, r.role_sort, r.data_scope, r.status as role_status,
-        u.is_need_register_member
+        u.is_need_register_member, u.is_allowed_all_register
         from company_user u
 		    left join company_dept d on u.dept_id = d.dept_id
 		    left join company_user_role ur on u.user_id = ur.user_id
@@ -573,4 +574,12 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         </foreach>
     </update>
 
+    <update id="updateAllowedAllRegister" parameterType="Long">
+        update company_user
+        set is_allowed_all_register = #{status} where user_id in
+        <foreach item="userId" collection="userIds" open="(" separator="," close=")">
+            #{userId}
+        </foreach>
+    </update>
+
 </mapper>

+ 15 - 7
fs-service-system/src/main/resources/mapper/course/FsUserCourseMapper.xml

@@ -267,6 +267,12 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         inner join fs_course_watch_log fcwl on fcwl.video_id = fucv.video_id
         inner join fs_user fu on fu.user_id = fcwl.user_id
         where fucv.video_id = #{params.videoId}
+        <if test="params.companyId != null">
+            and fcwl.company_id = #{params.companyId}
+        </if>
+        <if test="params.companyUserId != null">
+            and fcwl.company_user_id = #{params.companyUserId}
+        </if>
         <if test="params.keyword != null and params.keyword != ''">
             and (
                 fu.user_id = #{params.keyword}
@@ -278,20 +284,22 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         <choose>
             <when test="params.type == 0">
                 and (
-                    select count(log_id) as count
-                    from fs_course_answer_logs
-                    where user_id = fu.user_id and fcwl.video_id = fucv.video_id and is_right = 1
+                    select count(log.log_id) as count
+                    from fs_course_answer_logs log
+                    where log.user_id = fu.user_id and log.video_id = fucv.video_id and log.is_right = 1
+                ) > 0
+                and (
+                    select count(log.log_id) as count
+                    from fs_course_red_packet_log log
+                    where log.user_id = fu.user_id and log.video_id = fucv.video_id and log.status = 1
                 ) > 0
             </when>
             <when test="params.type == 1">
                 and fcwl.log_type = 2
             </when>
             <when test="params.type == 2">
-                and fcwl.log_type in (1,4)
+                and fcwl.log_type = 4
             </when>
-            <otherwise>
-                and fcwl.log_type = 3
-            </otherwise>
         </choose>
         group by fu.user_id, fucv.video_id, fu.nickname, fu.username, fu.avatar, fu.phone, fu.create_time
     </select>

+ 7 - 13
fs-service-system/src/main/resources/mapper/course/FsUserWatchStatisticsMapper.xml

@@ -104,27 +104,21 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             count( DISTINCT CASE WHEN fwl.log_type != 3 THEN fwl.user_id END ) AS watchNum,
             count( DISTINCT CASE WHEN fwl.log_type = 2 THEN fwl.user_id END ) AS completeWatchNum,
             ifnull(
-                ROUND(
-                    (
-                        COUNT( DISTINCT CASE WHEN fwl.log_type = 2 THEN fwl.user_id END ) / count( DISTINCT CASE WHEN fwl.log_type != 3 THEN fwl.user_id END )) * 100,
-                    2
+                    ROUND(
+                            (
+                                COUNT( DISTINCT CASE WHEN fwl.log_type = 2 THEN fwl.user_id END ) / count( DISTINCT CASE WHEN fwl.log_type != 3 THEN fwl.user_id END )) * 100,
+                            2
                     ),
                     0
             ) AS completeWatchRate,
-            fwl.period_id
-            ,fs_user_course_period.period_name,
-            fs_user_course_period.period_starting_time,
-            fs_user_course_period.company_id,
-            GROUP_CONCAT(DISTINCT company.company_name) company_name
+            fwl.period_id,
+            fwl.company_id
         FROM
             fs_course_watch_log fwl
-                LEFT JOIN fs_user_course_period ON fwl.period_id = fs_user_course_period.period_id
-                LEFT JOIN company ON FIND_IN_SET( company.company_id, fs_user_course_period.company_id ) > 0
         WHERE
             fwl.send_type = 1
-            and fs_user_course_period.period_name is not null
         GROUP BY
-            fwl.period_id
+            fwl.period_id, fwl.company_id
     </select>
 
     <insert id="insertFsUserWatchStatisticsTask" parameterType="FsUserWatchStatistics" useGeneratedKeys="true" keyProperty="id">

+ 17 - 0
fs-service-system/src/main/resources/mapper/crm/CrmCustomerLevelMapper.xml

@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.fs.crm.mapper.CrmCustomerLevelMapper">
+
+    <select id="selectCrmCustomerLevelVOList" resultType="com.fs.crm.vo.CrmCustomerLevelVO">
+        select
+            ccl.*
+        from crm_customer_level ccl
+        <where>
+            <if test="name != null and name != ''">
+                and ccl.name like concat('%', #{name}, '%')
+            </if>
+        </where>
+    </select>
+</mapper>

+ 20 - 3
fs-service-system/src/main/resources/mapper/crm/CrmCustomerMapper.xml

@@ -51,12 +51,15 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         <result property="visitTime"    column="visit_time"    />
         <result property="trafficSource"   column="traffic_source"    />
         <result property="importType"    column="import_type"    />
+        <result property="volume"    column="volume"    />
         <result property="thirdAccount"    column="third_account"    />
         <result property="clueId"    column="clue_id"    />
+        <result property="customerLevel"    column="customer_level"    />
+        <result property="isTop"    column="is_top"    />
     </resultMap>
 
     <sql id="selectCrmCustomerVo">
-        select customer_id, customer_code, customer_name, mobile, sex, weixin, remark, user_id, create_user_id, receive_user_id, customer_user_id, address,city_ids, location, detail_address, lng, lat, create_time, update_time, status, is_receive, dept_id, is_del, customer_type, receive_time, pool_time, company_id, is_line, source, tags,ext_json,visit_status,register_date,register_link_url,register_desc,register_submit_time,is_pool,register_type,pay_money,buy_count,source_code,push_time,push_code,visit_time,traffic_source,import_type,third_account,clue_id from crm_customer
+        select customer_id, customer_code, customer_name, mobile, sex, weixin, remark, user_id, create_user_id, receive_user_id, customer_user_id, address,city_ids, location, detail_address, lng, lat, create_time, update_time, status, is_receive, dept_id, is_del, customer_type, receive_time, pool_time, company_id, is_line, source, tags,ext_json,visit_status,register_date,register_link_url,register_desc,register_submit_time,is_pool,register_type,pay_money,buy_count,source_code,push_time,push_code,visit_time,traffic_source,import_type,third_account,clue_id,customer_level,is_top from crm_customer
     </sql>
 
     <select id="selectCrmCustomerList" parameterType="CrmCustomer" resultMap="CrmCustomerResult">
@@ -92,6 +95,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="importType != null "> and import_type = #{importType}</if>
             <if test="thirdAccount != null "> and third_account = #{thirdAccount}</if>
             <if test="clueId != null "> and clue_id = #{clueId}</if>
+            <if test="customerLevel != null "> and customer_level = #{customerLevel}</if>
+            <if test="isTop != null "> and is_top = #{isTop}</if>
         </where>
         order by customer_id desc
     </select>
@@ -156,6 +161,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="importType != null">import_type,</if>
             <if test="thirdAccount != null">third_account,</if>
             <if test="clueId != null">clue_id,</if>
+            <if test="customerLevel != null">customer_level,</if>
+            <if test="isTop != null">is_top,</if>
          </trim>
         <trim prefix="values (" suffix=")" suffixOverrides=",">
             <if test="customerCode != null">#{customerCode},</if>
@@ -205,6 +212,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="importType != null">#{importType},</if>
             <if test="thirdAccount != null">#{thirdAccount},</if>
             <if test="clueId != null">#{clueId},</if>
+            <if test="customerLevel != null">#{customerLevel},</if>
+            <if test="isTop != null">#{isTop},</if>
          </trim>
     </insert>
 
@@ -258,6 +267,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="importType != null">import_type = #{importType},</if>
             <if test="thirdAccount != null">third_account = #{thirdAccount},</if>
             <if test="clueId != null">clue_id = #{clueId},</if>
+            <if test="customerLevel != null">customer_level = #{customerLevel},</if>
+            <if test="isTop != null">is_top = #{isTop},</if>
         </trim>
         where customer_id = #{customerId}
     </update>
@@ -292,13 +303,16 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
     <select id="selectCrmMyCustomerListQuery" resultType="com.fs.crm.vo.CrmMyCustomerListQueryVO">
         select cu.*,c.create_time as customer_create_time,c.visit_status,c.remark,c.register_desc,c.register_submit_time,
                c.customer_code,c.customer_name,c.mobile,c.sex,c.weixin,c.address,c.is_receive,c.customer_type,c.source,
-               c.tags,c.receive_time
+               c.tags,c.receive_time,c.customer_level
         from crm_customer_user cu
             inner join crm_customer c on c.customer_user_id=cu.customer_user_id
         where cu.is_pool=0  and c.is_del = 0
         <if test="maps.companyId != null">
             and cu.company_id =#{maps.companyId}
         </if>
+        <if test="maps.customerLevel != null">
+            and c.customer_level =#{maps.customerLevel}
+        </if>
         <if test="maps.companyUserId != null">
             and cu.company_user_id =#{maps.companyUserId}
         </if>
@@ -358,7 +372,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
     <select id="selectCrmMyAssistListQuery" resultType="com.fs.crm.vo.CrmMyCustomerListQueryVO">
         select cu.*,c.create_time as customer_create_time,c.visit_status,c.remark,c.register_desc,c.register_submit_time,
         c.customer_code,c.customer_name,c.mobile,c.sex,c.weixin,c.address,c.is_receive,c.customer_type,c.source,
-        c.tags,c.receive_time
+        c.tags,c.receive_time, c.customer_level
         from crm_customer_assist ca
         LEFT JOIN  crm_customer c on c.customer_id=ca.customer_id
         LEFT JOIN crm_customer_user cu on c.customer_user_id=cu.customer_user_id
@@ -369,6 +383,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         <if test="maps.companyUserId != null">
             and ca.company_user_id =#{maps.companyUserId}
         </if>
+        <if test="maps.customerLevel != null">
+            and c.customer_level =#{maps.customerLevel}
+        </if>
         <if test="maps.address != null and  maps.address != ''">
             and c.address like CONCAT('%',#{maps.address},'%')
         </if>

+ 6 - 10
fs-service-system/src/main/resources/mapper/statis/ConsumptionBalanceMapper.xml

@@ -278,14 +278,12 @@
             <if test="dataType == 1">
                 rpl.course_id as course_id,
             </if>
-            SUM(rpl.money) as rewardMoney
+            SUM(rpl.amount) as rewardMoney
         FROM
-            company_red_package_logs rpl
-        left join fs_course_watch_log log
-        on rpl.watch_log_id=log.log_id
+            fs_course_red_packet_log rpl
+            left join fs_course_watch_log log
+            on rpl.watch_log_id=log.log_id
         <where>
-            rpl.operate_type = 1
-            AND rpl.status = 1
             <if test="startTime != null">
                 AND rpl.create_time <![CDATA[>=]]> #{startTime}
             </if>
@@ -320,8 +318,8 @@
         <if test="type == 2 or type == 3 or type == 4">
             DATE_FORMAT(rpl.create_time, '%Y-%m-%d') AS start_date,
         </if>
-               SUM(rpl.money) as rewardMoney
-        from company_red_package_logs rpl
+            SUM(rpl.amount) as rewardMoney
+        from fs_course_red_packet_log rpl
         left join fs_course_watch_log log
         on rpl.watch_log_id=log.log_id
         <where>
@@ -337,8 +335,6 @@
             <if test="companyId != null">
                 and log.company_id = ${companyId}
             </if>
-            AND rpl.operate_type = 1
-            AND rpl.status = 1
         </where>
         group by start_date
     </select>

+ 23 - 0
fs-service-system/src/main/resources/mapper/store/FsStoreOrderMapper.xml

@@ -507,4 +507,27 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             AND pay_time &lt; DATE_ADD(STR_TO_DATE(#{map.payTime}, '%Y-%m-%d'), INTERVAL 1 DAY)
         </if>
     </select>
+
+
+    <select id="selectFsStoreOrderCount" resultType="int">
+        select  count(id) from fs_store_order
+        <where>
+            <if test="startTime != null and startTime != ''">AND date_format(create_time,'%y%m%d') &gt;= date_format(#{startTime},'%y%m%d')</if>
+            <if test="endTime != null and endTime != ''">AND date_format(create_time,'%y%m%d') &lt;= date_format(#{endTime},'%y%m%d')</if>
+            <if test="status != null"> and status = #{status}</if>
+            <if test="paid != null and paid==1"> and pay_time is not null</if>
+            <if test="paid != null and paid==0"> and pay_time is null</if>
+        </where>
+
+    </select>
+
+    <select id="selectFsStoreOrderByPayPriceCount" resultType="java.math.BigDecimal">
+        select  sum(pay_price) from fs_store_order
+        <where>
+            <if test="paid != null"> and paid = #{paid}</if>
+            <if test="startTime != null and startTime != ''">AND date_format(create_time,'%y%m%d') &gt;= date_format(#{startTime},'%y%m%d')</if>
+            <if test="endTime != null and endTime != ''">AND date_format(create_time,'%y%m%d') &lt;= date_format(#{endTime},'%y%m%d')</if>
+        </where>
+
+    </select>
 </mapper>

+ 201 - 65
fs-service-system/src/main/resources/mapper/store/FsUserMapper.xml

@@ -618,9 +618,13 @@
             fs_user
                 LEFT JOIN fs_user_company_user ON fs_user_company_user.user_id = fs_user.user_id
                 LEFT JOIN company_user ON company_user.user_id = fs_user_company_user.company_user_id
-        WHERE
-           (company_user.user_id = #{userId} OR company_user.parent_id = #{userId} )
-            and fs_user.is_del = 0
+        WHERE fs_user.is_del = 0
+        <if test="userId != null and userId != 0 ">
+            and (fs_user.company_user_id = #{userId} OR company_user.parent_id = #{userId} )
+        </if>
+        <if test="companyId != null ">
+            and fs_user.company_id = #{companyId}
+        </if>
         GROUP BY
             fs_user.`status`
     </select>
@@ -640,8 +644,14 @@
 
     <select id="getCountWatchCourse" resultType="UserDetailsVO">
         SELECT
-        ifnull( complete_watch_count, 0 ) AS completeWatchCount ,
-        ifnull( watch_times, 0 ) AS watchTimes,
+        <if test="dateTag == null or dateTag =='' or dateTag == '近七天' ">
+            ifnull( sum(complete_watch_count), 0 ) AS completeWatchCount ,
+            ifnull( sum(watch_times), 0 ) AS watchTimes,
+        </if>
+        <if test="dateTag != null and dateTag !='' and dateTag != '近七天' ">
+            ifnull( complete_watch_count, 0 ) AS completeWatchCount ,
+            ifnull( watch_times, 0 ) AS watchTimes,
+        </if>
         fs_user.user_id
         FROM
         fs_user_course_count
@@ -664,11 +674,10 @@
                 </when>
             </choose>
         </if>
+           and fs_user.user_id = #{fsUserId}
         </where>
         GROUP BY
         fs_user.user_id
-        HAVING
-        fs_user.user_id = #{fsUserId}
     </select>
 
     <select id="getCountAnswer" resultType="UserDetailsVO">
@@ -680,8 +689,8 @@
                     fs_course_answer_logs
                         LEFT JOIN fs_user ON fs_user.user_id = fs_course_answer_logs.user_id
                         LEFT JOIN company_user ON company_user.user_id = fs_user.company_user_id
-                WHERE
-                (company_user.user_id = #{userId} or company_user.parent_id = #{userId} )
+                <where>
+
                     <if test="dateTag != null and dateTag !='' ">
                         <choose>
                             <when test = "dateTag == '今天'">
@@ -698,10 +707,10 @@
                             </when>
                         </choose>
                     </if>
+                and fs_user.user_id = #{fsUserId}
+                </where>
                 GROUP BY
                     fs_user.user_id
-                HAVING
-                    fs_user.user_id = #{fsUserId}
             ) AS answerTime,
             (
                 SELECT
@@ -710,9 +719,8 @@
                     fs_course_answer_logs
                         LEFT JOIN fs_user ON fs_user.user_id = fs_course_answer_logs.user_id
                         LEFT JOIN company_user ON company_user.user_id = fs_user.company_user_id
-                WHERE
-                (company_user.user_id = #{userId} or company_user.parent_id = #{userId} )
-                  AND fs_course_answer_logs.is_right = 1
+            <where>
+                fs_course_answer_logs.is_right = 1
                 <if test="dateTag != null and dateTag !='' ">
                     <choose>
                         <when test = "dateTag == '今天'">
@@ -729,10 +737,10 @@
                         </when>
                     </choose>
                 </if>
+                and fs_user.user_id = #{fsUserId}
+            </where>
                 GROUP BY
                     fs_user.user_id
-                HAVING
-                    fs_user.user_id = #{fsUserId}
             ) AS answerRightTime;
     </select>
 
@@ -745,9 +753,8 @@
             fs_course_red_packet_log
                 LEFT JOIN fs_user ON fs_user.user_id = fs_course_red_packet_log.user_id
                 LEFT JOIN company_user ON company_user.user_id = fs_user.company_user_id
-        WHERE
-        (company_user.user_id = #{userId} or company_user.parent_id = #{userId} )
-        and fs_course_red_packet_log.status = 1
+        <where>
+        fs_course_red_packet_log.status = 1
         <if test="dateTag != null and dateTag !='' ">
                 <choose>
                     <when test = "dateTag == '今天'">
@@ -764,10 +771,10 @@
                     </when>
                 </choose>
             </if>
+            and  fs_user.user_id = #{fsUserId}
+        </where>
         GROUP BY
         fs_user.user_id
-        HAVING
-        fs_user.user_id = #{fsUserId}
     </select>
 
     <select id="getUserVipCountByCompanyUserId" resultType="java.util.Map">
@@ -790,15 +797,24 @@
         SELECT (SELECT count(fs_user.user_id)
                 FROM fs_user
                          LEFT JOIN company_user ON fs_user.company_user_id = company_user.user_id
-                WHERE (
-                          company_user.user_id = #{userId}
-                              OR company_user.parent_id = #{userId}
-                          ) and fs_user.is_del = 0) as userTotal,
+                WHERE fs_user.is_del = 0
+                <if test="userId != null and userId != 0 ">
+                    and (fs_user.company_user_id = #{userId} OR company_user.parent_id = #{userId} )
+                </if>
+                <if test="companyId != null ">
+                    and fs_user.company_id = #{companyId}
+                </if>
+                  ) as userTotal,
                (SELECT count(fs_user.user_id)
                 FROM fs_user
                          LEFT JOIN company_user ON fs_user.company_user_id = company_user.user_id
-                WHERE (company_user.user_id = #{userId} OR company_user.parent_id = #{userId})
-                and fs_user.is_del = 0
+                WHERE fs_user.is_del = 0
+                <if test="userId != null and userId != 0 ">
+                    and (fs_user.company_user_id = #{userId} OR company_user.parent_id = #{userId} )
+                </if>
+                <if test="companyId != null ">
+                    and fs_user.company_id = #{companyId}
+                </if>
                   AND to_days(fs_user.create_time) = to_days(now())) as todayNewUser
     </select>
 
@@ -811,7 +827,15 @@
                 LEFT JOIN fs_user ON fs_user.user_id = company_tag_user.user_id
                 LEFT JOIN company_tag ON FIND_IN_SET( company_tag.tag_id, company_tag_user.tag_ids ) > 0
                 LEFT JOIN company_user ON fs_user.company_user_id = company_user.user_id
-        where (company_user.user_id = #{userId} or company_user.parent_id = #{userId} ) and company_tag.tag_id is not null
+        <where>
+        <if test="userId != null and userId != 0 ">
+            and (fs_user.company_user_id = #{userId} OR company_user.parent_id = #{userId} )
+        </if>
+        <if test="companyId != null ">
+            and fs_user.company_id = #{companyId}
+        </if>
+           and company_tag.tag_id is not null
+        </where>
         GROUP BY
             company_tag.tag_id
     </select>
@@ -826,8 +850,13 @@
                         LEFT JOIN fs_user ON fs_user.user_id = fcc.user_id
                         LEFT JOIN company_user ON fs_user.company_user_id = company_user.user_id
                         LEFT JOIN fs_user_course_period_days fcpd ON FIND_IN_SET(fcpd.period_id, fcc.course_ids) > 0
-        WHERE
-                    ( company_user.user_id = #{userId}  OR company_user.parent_id = #{userId}  )
+                <where>
+                    <if test="userId != null and userId != 0 ">
+                        and (fs_user.company_user_id = #{userId} OR company_user.parent_id = #{userId} )
+                    </if>
+                    <if test="userId != null and userId == 0 ">
+                        and fs_user.company_id = #{companyId}
+                    </if>
                     <if test="startTime != null and startTime !='' ">
                             and fcc.create_time &gt;= #{startTime}
                     </if>
@@ -844,7 +873,7 @@
                     <if test="companyUserId != null and companyUserId != ''">
                         AND company_user.user_id = #{companyUserId}
                     </if>
-
+                </where>
             ) as courseWatchNum,
             (
                 SELECT
@@ -854,8 +883,13 @@
                         LEFT JOIN fs_user ON fs_user.user_id = fcc.user_id
                         LEFT JOIN company_user ON fs_user.company_user_id = company_user.user_id
                         LEFT JOIN fs_user_course_period_days fcpd ON FIND_IN_SET(fcpd.period_id, fcc.course_ids) > 0
-                WHERE
-                    ( company_user.user_id = #{userId}  OR company_user.parent_id = #{userId}  )
+                <where>
+                    <if test="userId != null and userId != 0 ">
+                        and (fs_user.company_user_id = #{userId} OR company_user.parent_id = #{userId} )
+                    </if>
+                    <if test="userId != null and userId == 0 ">
+                        and fs_user.company_id = #{companyId}
+                    </if>
                   AND fcc.complete_watch_count > 0
                     <if test="startTime != null and startTime !='' ">
                         and fcc.create_time &gt;= #{startTime}
@@ -873,6 +907,7 @@
                     <if test="companyUserId != null and companyUserId != ''">
                         AND company_user.user_id = #{companyUserId}
                     </if>
+                </where>
             ) as courseCompleteNum
     </select>
 
@@ -885,8 +920,13 @@
         fs_course_answer_logs
         LEFT JOIN fs_user ON fs_user.user_id = fs_course_answer_logs.user_id
         LEFT JOIN company_user ON company_user.user_id = fs_user.company_user_id
-        WHERE
-        ( company_user.user_id = #{userId} OR company_user.parent_id = #{userId} )
+        <where>
+        <if test="userId != null and userId != 0 ">
+            and (fs_user.company_user_id = #{userId} OR company_user.parent_id = #{userId} )
+        </if>
+        <if test="userId != null and userId == 0 ">
+            and fs_user.company_id = #{companyId}
+        </if>
         <if test="startTime != null and startTime !='' ">
             AND fs_course_answer_logs.create_time &gt;= #{startTime}
         </if>
@@ -903,6 +943,7 @@
         <if test="companyUserId != null and companyUserId != ''">
             AND company_user.user_id = #{companyUserId}
         </if>
+        </where>
         ) AS answerNum,
         (
         SELECT
@@ -911,8 +952,13 @@
         fs_course_answer_logs
         LEFT JOIN fs_user ON fs_user.user_id = fs_course_answer_logs.user_id
         LEFT JOIN company_user ON company_user.user_id = fs_user.company_user_id
-        WHERE
-        ( company_user.user_id = #{userId} OR company_user.parent_id = #{userId} )
+        <where>
+        <if test="userId != null and userId != 0 ">
+            and (fs_user.company_user_id = #{userId} OR company_user.parent_id = #{userId} )
+        </if>
+        <if test="userId != null and userId == 0 ">
+            and fs_user.company_id = #{companyId}
+        </if>
         AND fs_course_answer_logs.is_right = 1
         <if test="startTime != null and startTime !='' ">
             AND fs_course_answer_logs.create_time &gt;= #{startTime}
@@ -930,6 +976,7 @@
         <if test="companyUserId != null and companyUserId != ''">
             AND company_user.user_id = #{companyUserId}
         </if>
+        </where>
         ) AS answerRightNum
     </select>
 
@@ -942,8 +989,13 @@
                 fs_course_red_packet_log flog
                     LEFT JOIN fs_user ON fs_user.user_id = flog.user_id
                     LEFT JOIN company_user ON company_user.user_id = fs_user.company_user_id
-            WHERE
-                ( company_user.user_id = #{userId}  OR company_user.parent_id = #{userId}  )
+                <where>
+                <if test="userId != null and userId != 0 ">
+                    and (fs_user.company_user_id = #{userId} OR company_user.parent_id = #{userId} )
+                </if>
+                <if test="userId != null and userId == 0 ">
+                    and fs_user.company_id = #{companyId}
+                </if>
                 <if test="startTime != null and startTime !='' ">
                     AND flog.create_time &gt;= #{startTime}
                 </if>
@@ -960,6 +1012,7 @@
                 <if test="companyUserId != null and companyUserId != ''">
                     AND company_user.user_id = #{companyUserId}
                 </if>
+                </where>
         ) AS redPacketNum,
         (
             SELECT
@@ -968,8 +1021,13 @@
                 fs_course_red_packet_log flog
                     LEFT JOIN fs_user ON fs_user.user_id = flog.user_id
                     LEFT JOIN company_user ON company_user.user_id = fs_user.company_user_id
-            WHERE
-                ( company_user.user_id = #{userId}  OR company_user.parent_id = #{userId}  )
+                <where>
+                <if test="userId != null and userId != 0 ">
+                    and (fs_user.company_user_id = #{userId} OR company_user.parent_id = #{userId} )
+                </if>
+                <if test="userId != null and userId == 0 ">
+                    and fs_user.company_id = #{companyId}
+                </if>
                 <if test="startTime != null and startTime !='' ">
                     AND flog.create_time &gt;= #{startTime}
                 </if>
@@ -986,6 +1044,7 @@
                 <if test="companyUserId != null and companyUserId != ''">
                     AND company_user.user_id = #{companyUserId}
                 </if>
+                </where>
         ) AS redPacketAmount
     </select>
 
@@ -999,9 +1058,12 @@
             LEFT JOIN fs_user ON fs_user.user_id = fcc.user_id
             WHERE 1=1
             AND FIND_IN_SET(#{companyId}, fpd.company_id)
-            <if test="userId != null and userId != ''">
+            <if test="userId != null and userId != 0 ">
                 AND fs_user.company_user_id = #{userId}
             </if>
+            <if test="userId != null and userId == 0 ">
+                and fs_user.company_id = #{companyId}
+            </if>
             <if test="periodId != null and periodId != ''">
                 AND fcpd.period_id =  #{periodId}
             </if>
@@ -1018,9 +1080,12 @@
             LEFT JOIN fs_user ON fs_user.user_id = fcc.user_id
             WHERE 1=1
             AND FIND_IN_SET(#{companyId}, fpd.company_id)
-            <if test="userId != null and userId != ''">
+            <if test="userId != null and userId != 0 ">
                 AND fs_user.company_user_id = #{userId}
             </if>
+            <if test="userId != null and userId == 0 ">
+                and fs_user.company_id = #{companyId}
+            </if>
             <if test="periodId != null and periodId != ''">
                 AND fcpd.period_id =  #{periodId}
             </if>
@@ -1047,9 +1112,12 @@
             AND fs_user.company_user_id = #{companyUserId}
         </if>
         <where>
-            <if test="userId != null and userId != ''">
+            <if test="userId != null and userId != 0 ">
                 AND fs_user.company_user_id = #{userId}
             </if>
+            <if test="userId != null and userId == 0 ">
+                and fs_user.company_id = #{companyId}
+            </if>
         </where>
          ) as courseUserNum
     </select>
@@ -1065,8 +1133,13 @@
         LEFT JOIN fs_user ON fs_user.user_id = fcc.user_id
         LEFT JOIN company_user ON fs_user.company_user_id = company_user.user_id
         LEFT JOIN fs_user_course_period_days fcpd ON FIND_IN_SET( fcpd.period_id, fcc.course_ids ) > 0
-        WHERE
-        ( company_user.user_id = #{userId} OR company_user.parent_id = #{userId} )
+        <where>
+        <if test="userId != null and userId != 0 ">
+            AND  ( fs_user.company_user_id = #{userId} OR company_user.parent_id = #{userId} )
+        </if>
+        <if test="userId != null and userId == 0 ">
+            and fs_user.company_id = #{companyId}
+        </if>
         <if test="startTime != null and startTime !='' ">
             AND fcc.create_time &gt;= #{startTime}
         </if>
@@ -1079,6 +1152,7 @@
         <if test="videoId != null and videoId != ''">
             AND fcpd.video_id = #{videoId}
         </if>
+        </where>
         group by fcc.user_id
         <choose>
             <when test="order != null and order == 'asc'">
@@ -1105,8 +1179,13 @@
             fs_course_answer_logs
                 LEFT JOIN fs_user ON fs_user.user_id = fs_course_answer_logs.user_id
                 LEFT JOIN company_user ON company_user.user_id = fs_user.company_user_id
-        WHERE
-        ( company_user.user_id = #{userId} OR company_user.parent_id = #{userId} )
+            <where>
+            <if test="userId != null and userId != 0 ">
+                AND  ( fs_user.company_user_id = #{userId} OR company_user.parent_id = #{userId} )
+            </if>
+            <if test="userId != null and userId == 0 ">
+                and fs_user.company_id = #{companyId}
+            </if>
             <if test="startTime != null and startTime !='' ">
                 AND fs_course_answer_logs.create_time &gt;= #{startTime}
             </if>
@@ -1119,6 +1198,7 @@
             <if test="videoId != null and videoId != ''">
                 AND fs_course_answer_logs.video_id = #{videoId}
             </if>
+            </where>
         group by fs_user.user_id
         <choose>
             <when test="order != null and order == 'asc'">
@@ -1150,8 +1230,13 @@
         LEFT JOIN company_user ON fs_user.company_user_id = company_user.user_id
         LEFT JOIN fs_user_course_period_days fcpd ON FIND_IN_SET( fcpd.period_id, fcc.course_ids ) > 0
         LEFT JOIN fs_user_course_video fcv ON fcv.video_id = fcpd.video_id
-        WHERE
-        ( company_user.user_id = #{userId} OR company_user.parent_id = #{userId} )
+        <where>
+        <if test="userId != null and userId != 0 ">
+            AND ( fs_user.company_user_id = #{userId} OR company_user.parent_id = #{userId} )
+        </if>
+        <if test="userId != null and userId == 0 ">
+            and fs_user.company_id = #{companyId}
+        </if>
         <if test="startTime != null and startTime !='' ">
             AND fcc.create_time &gt;= #{startTime}
         </if>
@@ -1164,6 +1249,7 @@
         <if test="videoId != null and videoId != ''">
             AND fcpd.video_id = #{videoId}
         </if>
+        </where>
         GROUP BY
         fcpd.video_id
         <choose>
@@ -1196,8 +1282,13 @@
         LEFT JOIN fs_user ON fs_user.user_id = fs_course_answer_logs.user_id
         LEFT JOIN company_user ON company_user.user_id = fs_user.company_user_id
         LEFT JOIN fs_user_course_video fcv ON fcv.video_id = fs_course_answer_logs.video_id
-        WHERE
-        ( company_user.user_id = #{userId} OR company_user.parent_id = #{userId} )
+        <where>
+        <if test="userId != null and userId != 0 ">
+            AND ( fs_user.company_user_id = #{userId} OR company_user.parent_id = #{userId} )
+        </if>
+        <if test="userId != null and userId == 0 ">
+            and fs_user.company_id = #{companyId}
+        </if>
         <if test="startTime != null and startTime !='' ">
             AND fs_course_answer_logs.create_time &gt;= #{startTime}
         </if>
@@ -1210,6 +1301,7 @@
         <if test="videoId != null and videoId != ''">
             AND fs_course_answer_logs.video_id = #{videoId}
         </if>
+        </where>
         GROUP BY
         fs_course_answer_logs.video_id
         <choose>
@@ -1245,14 +1337,20 @@
         LEFT JOIN fs_user ON fs_user.user_id = fcc.user_id
         LEFT JOIN company_user ON fs_user.company_user_id = company_user.user_id
         LEFT JOIN fs_user_course_period_days fcpd ON FIND_IN_SET( fcpd.period_id, fcc.course_ids ) > 0
-        WHERE
-        company_user.user_id = #{companyUserId}
+        <where>
+        <if test="companyUserId != null and companyUserId != 0 ">
+            AND fs_user.company_user_id = #{companyUserId}
+        </if>
+        <if test="companyUserId != null and companyUserId == 0 ">
+            and fs_user.company_id = #{companyId}
+        </if>
         <if test="periodId != null and periodId != ''">
             AND fcpd.period_id =  #{periodId}
         </if>
         <if test="videoId != null and videoId != ''">
             AND fcpd.video_id = #{videoId}
         </if>
+        </where>
         GROUP BY
         fcpd.video_id
     </select>
@@ -1268,8 +1366,11 @@
         LEFT JOIN fs_user ON fs_user.user_id = flog.user_id
         LEFT JOIN company_user ON company_user.user_id = fs_user.company_user_id
         <where>
-            <if test="companyUserId != null and companyUserId !='' ">
-                AND company_user.user_id = #{companyUserId}
+            <if test="companyUserId != null and companyUserId != 0 ">
+                AND fs_user.company_user_id = #{companyUserId}
+            </if>
+            <if test="companyUserId != null and companyUserId == 0 ">
+                and fs_user.company_id = #{companyId}
             </if>
             <if test="periodId != null and periodId != ''">
                 AND flog.period_id =  #{periodId}
@@ -1309,8 +1410,11 @@
         LEFT JOIN fs_user ON fs_user.user_id = fs_course_answer_logs.user_id
         LEFT JOIN company_user ON company_user.user_id = fs_user.company_user_id
         <where>
-            <if test="companyUserId != null and companyUserId !='' ">
-                AND company_user.user_id = #{companyUserId}
+            <if test="companyUserId != null and companyUserId != 0 ">
+                AND fs_user.company_user_id = #{companyUserId}
+            </if>
+            <if test="companyUserId != null and companyUserId == 0 ">
+                and fs_user.company_id = #{companyId}
             </if>
             <if test="periodId != null and periodId != ''">
                 AND fs_course_answer_logs.period_id =  #{periodId}
@@ -1334,7 +1438,14 @@
         SELECT
             (
                 SELECT count( fs_user.user_id ) FROM fs_user LEFT JOIN company_user ON fs_user.company_user_id = company_user.user_id
-                WHERE company_user.user_id = #{companyUserId}
+            <where>
+                <if test="companyUserId != null and companyUserId != '' and companyUserId != '0' ">
+                    AND fs_user.company_user_id = #{companyUserId}
+                </if>
+                <if test="companyUserId != null and companyUserId != '' and companyUserId == '0' ">
+                    and fs_user.company_id = #{companyId}
+                </if>
+            </where>
             ) AS userTotal,
             (
                 SELECT
@@ -1342,11 +1453,17 @@
                 FROM
                     fs_user
                         LEFT JOIN company_user ON fs_user.company_user_id = company_user.user_id
-                WHERE
-                    company_user.user_id = #{companyUserId}
+                <where>
+                    <if test="companyUserId != null and companyUserId != '' and companyUserId != '0' ">
+                        AND fs_user.company_user_id = #{companyUserId}
+                    </if>
+                    <if test="companyUserId != null and companyUserId != '' and companyUserId == '0' ">
+                        and fs_user.company_id = #{companyId}
+                    </if>
                   and fs_user.is_del = 0
                   AND to_days( fs_user.create_time ) = to_days(
                         now())
+                 </where>
             ) AS todayNewUser
     </select>
 
@@ -1357,8 +1474,14 @@
         FROM
             fs_course_red_packet_log flog
                 LEFT JOIN fs_user ON fs_user.user_id = flog.user_id
-        WHERE
-            fs_user.company_user_id = #{companyUserId}
+        <where>
+        <if test="companyUserId != null and companyUserId != '' and companyUserId != '0' ">
+            AND fs_user.company_user_id = #{companyUserId}
+        </if>
+        <if test="companyUserId != null and companyUserId != '' and companyUserId == '0' ">
+            and fs_user.company_id = #{companyId}
+        </if>
+        </where>
     </select>
 
     <select id="selectFsUserPageListCount" resultType="java.lang.Long">
@@ -1434,6 +1557,17 @@
         </foreach>
     </update>
 
+    <update id="batchUpdateCompanyUserRelation">
+        update fs_user_company_user
+        set company_id = #{companyId},
+        company_user_id = #{companyUserId}
+        where is_repeat_fans = 0 and
+        <foreach collection="userIds" open="(" close=")" separator="or" item="userId" index="index">
+           user_id = #{userId}
+        </foreach>
+    </update>
+
+
     <select id="selectUserListByMap" resultType="com.fs.his.vo.OptionsVO">
         select
             u.user_id dictValue,
@@ -1462,15 +1596,17 @@
     <select id="selectFsUserTotal" resultType="FsUserWatchStatistics">
         SELECT
             count( fs_user.user_id ) as userNum,
-            count( DISTINCT CASE WHEN to_days( fs_user.create_time ) = to_days( now()) THEN fs_user.user_id END ) as newUserNum
+            count( DISTINCT CASE WHEN to_days( fs_user.create_time ) = to_days( now()) THEN fs_user.user_id END ) as newUserNum,
+            fs_user.company_id
         FROM
             fs_user
             LEFT JOIN company_user ON company_user.user_id = fs_user.company_user_id
-            LEFT JOIN company ON company.company_id = fs_user.company_id
         WHERE
             fs_user.is_del = 0
           AND fs_user.`status` = 1
           AND company_user.user_id is not null
+        GROUP BY
+            fs_user.company_id
     </select>
 
 

部分文件因为文件数量过多而无法显示