Explorar o código

Merge remote-tracking branch 'origin/master'

zyp hai 1 semana
pai
achega
6dab41fcb3
Modificáronse 46 ficheiros con 364 adicións e 232 borrados
  1. 4 2
      fs-admin/src/main/java/com/fs/course/controller/FsCourseRedPacketLogController.java
  2. 11 2
      fs-admin/src/main/java/com/fs/course/controller/FsCourseTrafficLogController.java
  3. 2 1
      fs-admin/src/main/java/com/fs/course/controller/FsUserCourseController.java
  4. 3 0
      fs-admin/src/main/java/com/fs/course/controller/FsUserCourseVideoController.java
  5. 18 0
      fs-admin/src/main/java/com/fs/course/controller/FsUserWatchCourseStatisticsController.java
  6. 10 0
      fs-admin/src/main/java/com/fs/course/controller/FsUserWatchStatisticsController.java
  7. 4 2
      fs-admin/src/main/java/com/fs/qw/controller/QwSopController.java
  8. 23 0
      fs-admin/src/test/java/com/fs/course/controller/FsCourseDomainNameControllerTest.java
  9. 0 137
      fs-company-app/src/main/resources/application-druid-fby.yml
  10. 11 0
      fs-company/src/main/java/com/fs/company/controller/CompanyUserController.java
  11. 2 2
      fs-company/src/main/java/com/fs/course/controller/FsCourseRedPacketLogController.java
  12. 1 1
      fs-company/src/main/java/com/fs/course/controller/FsCourseTrafficLogController.java
  13. 1 1
      fs-company/src/main/java/com/fs/course/controller/FsUserCourseController.java
  14. 20 17
      fs-company/src/main/java/com/fs/course/controller/FsUserCourseVideoController.java
  15. 18 0
      fs-company/src/main/java/com/fs/course/controller/FsUserWatchCourseStatisticsController.java
  16. 1 1
      fs-company/src/main/java/com/fs/qw/QwSopController.java
  17. 11 0
      fs-service-system/src/main/java/com/fs/company/domain/CompanyUser.java
  18. 3 0
      fs-service-system/src/main/java/com/fs/company/mapper/CompanyMapper.java
  19. 3 0
      fs-service-system/src/main/java/com/fs/company/mapper/CompanyUserMapper.java
  20. 9 0
      fs-service-system/src/main/java/com/fs/company/service/ICompanyUserService.java
  21. 9 1
      fs-service-system/src/main/java/com/fs/company/service/impl/CompanyRechargeServiceImpl.java
  22. 15 1
      fs-service-system/src/main/java/com/fs/company/service/impl/CompanyUserServiceImpl.java
  23. 4 0
      fs-service-system/src/main/java/com/fs/company/vo/CompanyUserQwListVO.java
  24. 10 2
      fs-service-system/src/main/java/com/fs/course/domain/FsUserWatchCourseStatistics.java
  25. 4 1
      fs-service-system/src/main/java/com/fs/course/domain/FsUserWatchStatistics.java
  26. 1 2
      fs-service-system/src/main/java/com/fs/course/mapper/FsUserCourseMapper.java
  27. 1 2
      fs-service-system/src/main/java/com/fs/course/mapper/FsUserCourseVideoMapper.java
  28. 1 0
      fs-service-system/src/main/java/com/fs/course/param/BatchVideoSvae.java
  29. 1 1
      fs-service-system/src/main/java/com/fs/course/service/IFsUserCourseService.java
  30. 2 2
      fs-service-system/src/main/java/com/fs/course/service/impl/FsUserCourseServiceImpl.java
  31. 1 0
      fs-service-system/src/main/java/com/fs/course/service/impl/FsUserCourseVideoServiceImpl.java
  32. 67 26
      fs-service-system/src/main/java/com/fs/course/service/impl/FsUserWatchStatisticsServiceImpl.java
  33. 5 1
      fs-service-system/src/main/java/com/fs/course/vo/FsUserWatchCourseStatisticsExportVO.java
  34. 5 1
      fs-service-system/src/main/java/com/fs/statis/service/impl/StatisticsCompanyServiceImpl.java
  35. 2 0
      fs-service-system/src/main/java/com/fs/store/mapper/FsUserMapper.java
  36. 4 0
      fs-service-system/src/main/java/com/fs/store/service/impl/FsUserServiceImpl.java
  37. 1 1
      fs-service-system/src/main/resources/application-config-fby.yml
  38. 5 1
      fs-service-system/src/main/resources/db/upgrade/20250621客户分级.sql
  39. 8 0
      fs-service-system/src/main/resources/mapper/company/CompanyMapper.xml
  40. 10 1
      fs-service-system/src/main/resources/mapper/company/CompanyUserMapper.xml
  41. 7 0
      fs-service-system/src/main/resources/mapper/course/FsUserCourseMapper.xml
  42. 15 3
      fs-service-system/src/main/resources/mapper/course/FsUserCourseVideoMapper.xml
  43. 7 13
      fs-service-system/src/main/resources/mapper/course/FsUserWatchStatisticsMapper.xml
  44. 17 4
      fs-service-system/src/main/resources/mapper/store/FsUserMapper.xml
  45. 6 2
      fs-user-app/src/main/java/com/fs/app/controller/WxCompanyUserController.java
  46. 1 1
      fs-user-app/src/main/java/com/fs/app/controller/WxH5MpController.java

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

@@ -122,14 +122,16 @@ public class FsCourseRedPacketLogController extends BaseController
     @GetMapping("/courseList")
     public R courseList()
     {
-        List<OptionsVO> optionsVOS = fsUserCourseMapper.selectFsUserCourseAllList();
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        List<OptionsVO> optionsVOS = fsUserCourseMapper.selectFsUserCourseAllList(loginUser.getUser().getUserId());
         return R.ok().put("list", optionsVOS);
     }
 
     @GetMapping(value = "/videoList/{id}")
     public R videoList(@PathVariable("id") Long id)
     {
-        List<OptionsVO> optionsVOS = fsUserCourseVideoMapper.selectFsUserCourseVodeAllList(id);
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        List<OptionsVO> optionsVOS = fsUserCourseVideoMapper.selectFsUserCourseVodeAllList(id,loginUser.getUser().getUserId());
         return R.ok().put("list", optionsVOS);
     }
 }

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

@@ -7,7 +7,10 @@ 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.ServletUtils;
 import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.core.security.LoginUser;
+import com.fs.core.web.service.TokenService;
 import com.fs.course.domain.FsCourseTrafficLog;
 import com.fs.course.mapper.FsUserCourseVideoMapper;
 import com.fs.course.param.FsCourseTrafficLogParam;
@@ -43,6 +46,8 @@ public class FsCourseTrafficLogController extends BaseController
     private IFsUserCourseService fsUserCourseMapper;
     @Autowired
     private FsUserCourseVideoMapper fsUserCourseVideoMapper;
+    @Autowired
+    private TokenService tokenService;
     /**
      * 查询短链课程流量记录列表
      */
@@ -121,14 +126,18 @@ public class FsCourseTrafficLogController extends BaseController
     @GetMapping("/courseList")
     public R courseList()
     {
-        List<OptionsVO> optionsVOS = fsUserCourseMapper.selectFsUserCourseAllList();
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        List<OptionsVO> optionsVOS = fsUserCourseMapper.selectFsUserCourseAllList(loginUser.getUser().getUserId());
         return R.ok().put("list", optionsVOS);
     }
 
     @GetMapping(value = "/videoList/{id}")
     public R videoList(@PathVariable("id") Long id)
     {
-        List<OptionsVO> optionsVOS = fsUserCourseVideoMapper.selectFsUserCourseVodeAllList(id);
+
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+
+        List<OptionsVO> optionsVOS = fsUserCourseVideoMapper.selectFsUserCourseVodeAllList(id,loginUser.getUser().getUserId());
         return R.ok().put("list", optionsVOS);
     }
 }

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

@@ -194,7 +194,8 @@ public class FsUserCourseController extends BaseController
     @GetMapping("/getAllList")
     public R getAllList()
     {
-        List<OptionsVO> list = fsUserCourseService.selectFsUserCourseAllList();
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        List<OptionsVO> list = fsUserCourseService.selectFsUserCourseAllList(loginUser.getUser().getUserId());
         return R.ok().put("data", list);
     }
 

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

@@ -151,6 +151,9 @@ public class FsUserCourseVideoController extends BaseController
     }
     @PostMapping("/batchSaveVideo")
     public R batchSaveVideo(@RequestBody BatchVideoSvae vo){
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        Long userId = loginUser.getUser().getUserId();
+        vo.setUserId(userId);
         fsUserCourseVideoService.batchSaveVideo(vo);
         return R.ok();
     }

+ 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, "会员看课统计-按营期统计数据");
     }

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

@@ -77,14 +77,16 @@ public class QwSopController extends BaseController
     @GetMapping("/courseList")
     public R courseList()
     {
-        List<OptionsVO> optionsVOS = fsUserCourseMapper.selectFsUserCourseAllList();
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        List<OptionsVO> optionsVOS = fsUserCourseMapper.selectFsUserCourseAllList(loginUser.getUser().getUserId());
         return R.ok().put("list", optionsVOS);
     }
 
     @GetMapping(value = "/videoList/{id}")
     public R videoList(@PathVariable("id") Long id)
     {
-        List<OptionsVO> optionsVOS = fsUserCourseVideoMapper.selectFsUserCourseVodeAllList(id);
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        List<OptionsVO> optionsVOS = fsUserCourseVideoMapper.selectFsUserCourseVodeAllList(id,loginUser.getUser().getUserId());
         return R.ok().put("list", optionsVOS);
     }
     /**

+ 23 - 0
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;
@@ -75,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);
+    }
+
 }

+ 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

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

@@ -361,4 +361,15 @@ public class CompanyUserController extends BaseController {
         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("操作失败");
+        }
+    }
+
 }

+ 2 - 2
fs-company/src/main/java/com/fs/course/controller/FsCourseRedPacketLogController.java

@@ -169,14 +169,14 @@ public class FsCourseRedPacketLogController extends BaseController
     @GetMapping("/courseList")
     public R courseList()
     {
-        List<OptionsVO> optionsVOS = fsUserCourseMapper.selectFsUserCourseAllList();
+        List<OptionsVO> optionsVOS = fsUserCourseMapper.selectFsUserCourseAllList(null);
         return R.ok().put("list", optionsVOS);
     }
 
     @GetMapping(value = "/videoList/{id}")
     public R videoList(@PathVariable("id") Long id)
     {
-        List<OptionsVO> optionsVOS = fsUserCourseVideoMapper.selectFsUserCourseVodeAllList(id);
+        List<OptionsVO> optionsVOS = fsUserCourseVideoMapper.selectFsUserCourseVodeAllList(id,null);
         return R.ok().put("list", optionsVOS);
     }
 }

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

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

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

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

+ 20 - 17
fs-company/src/main/java/com/fs/course/controller/FsUserCourseVideoController.java

@@ -70,25 +70,28 @@ public class FsUserCourseVideoController extends BaseController
     @GetMapping(value = "/{videoId}")
     public AjaxResult getInfo(@PathVariable("videoId") Long videoId)
     {
-        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
-
-        return AjaxResult.success(fsUserCourseVideoService.selectFsUserCourseVideoByVideoIdVO(videoId,loginUser.getUser().getUserId()));
+        return AjaxResult.success(fsUserCourseVideoService.selectFsUserCourseVideoByVideoIdVO(videoId,null));
     }
 
-    /**
-     * 新增课堂视频
-     */
-    @PreAuthorize("@ss.hasPermi('course:userCourseVideo:add')")
-    @Log(title = "课堂视频", businessType = BusinessType.INSERT)
-    @PostMapping
-    public AjaxResult add(@RequestBody FsUserCourseVideo fsUserCourseVideo)
-    {
-        Long count = fsUserCourseVideoMapper.selectFsUserCourseVideoByCourseSort(fsUserCourseVideo.getCourseId(),fsUserCourseVideo.getCourseSort());
-        if (count>0){
-            return AjaxResult.error("课程排序重复");
-        }
-        return toAjax(fsUserCourseVideoService.insertFsUserCourseVideo(fsUserCourseVideo));
-    }
+
+
+
+
+
+//    /**
+//     * 新增课堂视频 如果需要开放此功能需要考虑user_id,admin有加这个参数
+//     */
+//    @PreAuthorize("@ss.hasPermi('course:userCourseVideo:add')")
+//    @Log(title = "课堂视频", businessType = BusinessType.INSERT)
+//    @PostMapping
+//    public AjaxResult add(@RequestBody FsUserCourseVideo fsUserCourseVideo)
+//    {
+//        Long count = fsUserCourseVideoMapper.selectFsUserCourseVideoByCourseSort(fsUserCourseVideo.getCourseId(),fsUserCourseVideo.getCourseSort());
+//        if (count>0){
+//            return AjaxResult.error("课程排序重复");
+//        }
+//        return toAjax(fsUserCourseVideoService.insertFsUserCourseVideo(fsUserCourseVideo));
+//    }
 
     /**
      * 修改课堂视频

+ 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);

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

@@ -96,7 +96,7 @@ public class QwSopController extends BaseController
     @GetMapping(value = "/videoList/{id}")
     public R videoList(@PathVariable("id") Long id)
     {
-        List<OptionsVO> optionsVOS = fsUserCourseVideoMapper.selectFsUserCourseVodeAllList(id);
+        List<OptionsVO> optionsVOS = fsUserCourseVideoMapper.selectFsUserCourseVodeAllList(id,null);
         return R.ok().put("list", optionsVOS);
     }
     /**

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

@@ -148,6 +148,9 @@ public class CompanyUser extends BaseEntity
     /** 是否需要单独注册会员,1-是,0-否(用于个微销售分享看课) */
     private Integer isNeedRegisterMember;
 
+    /** 是否允许所有方式注册会员,1-是,0-否,默认1(用于个微注册会员) */
+    private Integer isAllowedAllRegister;
+
     public double getVolume() {
         return volume;
     }
@@ -515,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;
+    }
 }

+ 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);
+
 }

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

@@ -295,4 +295,7 @@ public interface CompanyUserMapper
 
     @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);
+
 }

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

@@ -205,4 +205,13 @@ 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);
+
 }

+ 9 - 1
fs-service-system/src/main/java/com/fs/company/service/impl/CompanyRechargeServiceImpl.java

@@ -4,6 +4,8 @@ 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;
@@ -17,6 +19,7 @@ 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;
@@ -31,6 +34,7 @@ import org.springframework.transaction.annotation.Transactional;
  * @author fs
  * @date 2021-10-04
  */
+@Slf4j
 @Service
 public class CompanyRechargeServiceImpl implements ICompanyRechargeService
 {
@@ -153,9 +157,13 @@ public class CompanyRechargeServiceImpl implements ICompanyRechargeService
     private CompanyRechargeOrderMapper companyRechargeOrderMapper;
 
     @Override
-    public R payNotify(String orderNo,String transactionId) {
+    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);

+ 15 - 1
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集合

+ 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;
+
 }

+ 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 - 2
fs-service-system/src/main/java/com/fs/course/mapper/FsUserCourseMapper.java

@@ -128,8 +128,7 @@ public interface FsUserCourseMapper
             "</script>"})
     List<FsUserCourseListUVO> selectFsUserCourseListUVO(@Param("maps") FsUserCourseListUParam param);
 
-    @Select("select course_id dict_value, course_name dict_label,img_url dict_imgUrl  from fs_user_course where is_del = 0 and is_private = 1 ")
-    List<OptionsVO> selectFsUserCourseAllList();
+    List<OptionsVO> selectFsUserCourseAllList(@Param("userId") Long userId);
 
 
     @Select({"<script> " +

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

@@ -136,8 +136,7 @@ public interface FsUserCourseVideoMapper
     Long selectFsUserCourseVideoByCourseSort(@Param("courseId")Long courseId, @Param("courseSort")Long courseSort);
 
 
-    @Select("select video_id dict_value, title dict_label  from fs_user_course_video where course_id=#{id} and is_del = 0 ")
-    List<OptionsVO> selectFsUserCourseVodeAllList(Long id);
+    List<OptionsVO> selectFsUserCourseVodeAllList(@Param("id") Long id,@Param("userId")Long userId);
 
     @Select({"<script> " +
             "select v.*,p.red_packet_money company_red_packet_money from fs_user_course_video v LEFT JOIN fs_user_course_video_red_package p on p.video_id= v.video_id and p.company_id =#{maps.companyId} " +

+ 1 - 0
fs-service-system/src/main/java/com/fs/course/param/BatchVideoSvae.java

@@ -10,5 +10,6 @@ import java.util.List;
 @Data
 public class BatchVideoSvae {
     private Long courseId;
+    private Long userId;
     private List<Long> ids;
 }

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

@@ -83,7 +83,7 @@ public interface IFsUserCourseService
 
     List<FsUserCourseListUVO> selectFsUserCourseListUVO(FsUserCourseListUParam param);
 
-    List<OptionsVO> selectFsUserCourseAllList();
+    List<OptionsVO> selectFsUserCourseAllList(Long userId);
 
     List<FsUserCourseListPVO> selectFsUserCourseListPVO(FsUserCourse param);
 

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

@@ -220,8 +220,8 @@ public class FsUserCourseServiceImpl implements IFsUserCourseService
     }
 
     @Override
-    public List<OptionsVO> selectFsUserCourseAllList() {
-        return fsUserCourseMapper.selectFsUserCourseAllList();
+    public List<OptionsVO> selectFsUserCourseAllList(Long userId) {
+        return fsUserCourseMapper.selectFsUserCourseAllList(userId);
     }
 
 

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

@@ -1271,6 +1271,7 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
             entity.setFileSize(e.getFileSize());
             entity.setFileKey(e.getFileKey());
             entity.setIsTranscode(0);
+            entity.setUserId(vo.getUserId());
             return entity;
         }).collect(Collectors.toList());
         fsUserCourseVideoMapper.insertBatchFsUserCourseVideo(collect);

+ 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;

+ 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

+ 2 - 0
fs-service-system/src/main/java/com/fs/store/mapper/FsUserMapper.java

@@ -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    参数

+ 4 - 0
fs-service-system/src/main/java/com/fs/store/service/impl/FsUserServiceImpl.java

@@ -908,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);

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

@@ -103,7 +103,7 @@ wx:
       timeout: 2000
     configs:
       - appId: wx961fadab9bcb792b # 第一个公众号的appid  //公众号名称:云联
-        secret: eddde2a1d4ca0c6c443a67e542b6864c
+        secret: 8adb2a7533921449ef6e60814c2ff075
         token: PPKOdAlCoMO # 接口配置里的Token值
         aesKey: Eswa6VjwtVMCcw03qZy6fWllgrv5aytIA1SZPEU0kU2 # 接口配置里的EncodingAESKey值
 jpush:

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

@@ -11,4 +11,8 @@ create table crm_customer_level (
 -- 客户表新增级别字段、置顶字段
 alter table crm_customer
     add column `customer_level` bigint comment '客户级别' after `customer_type`,
-    add column `is_top` tinyint default 0 comment '是否置顶 0未置顶 1置顶';
+    add column `is_top` tinyint default 0 comment '是否置顶 0未置顶 1置顶';
+
+ALTER TABLE company_user ADD volume DOUBLE NULL COMMENT '音量';
+
+ALTER TABLE company_user ADD is_allowed_all_register1 TINYINT DEFAULT 1 NULL COMMENT '是否允许所有方式注册会员,1-是 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>

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

@@ -326,4 +326,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         </if>
         order by c.course_id
     </select>
+    <select id="selectFsUserCourseAllList" resultType="com.fs.his.vo.OptionsVO">
+        select course_id dict_value, course_name dict_label,img_url dict_imgUrl  from fs_user_course
+                                                                                 where is_del = 0 and is_private = 1
+        <if test="userId != null">
+            and user_id = #{userId}
+        </if>
+    </select>
 </mapper>

+ 15 - 3
fs-service-system/src/main/resources/mapper/course/FsUserCourseVideoMapper.xml

@@ -149,7 +149,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         red_packet_money,
         file_size,
         file_key,
-        is_transcode
+        is_transcode,
+        user_id
         )
         values
         <foreach collection="collect" item="item" separator=",">
@@ -169,7 +170,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             #{item.redPacketMoney},
             #{item.fileSize},
             #{item.fileKey},
-            #{item.isTranscode}
+            #{item.isTranscode},
+            #{item.userId}
             )
         </foreach>
     </insert>
@@ -313,7 +315,17 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         order by video.course_sort
     </select>
     <select id="selectFsUserCourseVideoByVideoIdAndUserId" resultType="com.fs.course.domain.FsUserCourseVideo">
-
+        select *  from fs_user_course_video
+                                                      where video_id=#{videoId} and is_del = 0
+        <if test="userId != null">
+            user_id = #{userId}
+        </if>
+    </select>
+    <select id="selectFsUserCourseVodeAllList" resultType="com.fs.his.vo.OptionsVO">
+        select video_id dict_value, title dict_label  from fs_user_course_video where course_id=#{id} and is_del = 0
+        <if test="userId != null">
+            and user_id = #{userId}
+        </if>
     </select>
 
     <update id="updateRedPacketMoney">

+ 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 - 4
fs-service-system/src/main/resources/mapper/store/FsUserMapper.xml

@@ -644,11 +644,11 @@
 
     <select id="getCountWatchCourse" resultType="UserDetailsVO">
         SELECT
-        <if test="dateTag == null or dateTag =='' ">
+        <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 !='' ">
+        <if test="dateTag != null and dateTag !='' and dateTag != '近七天' ">
             ifnull( complete_watch_count, 0 ) AS completeWatchCount ,
             ifnull( watch_times, 0 ) AS watchTimes,
         </if>
@@ -1557,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,
@@ -1585,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>
 
 

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

@@ -168,7 +168,9 @@ public class WxCompanyUserController extends AppBaseController {
                     if (user.getCompanyUserId() != null && !param.getCompanyUserId().equals(user.getCompanyUserId())){
                         return R.error(406, "该用户已成为其他销售会员");
                     }
-                    if(companyUser != null && companyUser.getIsNeedRegisterMember() != null && companyUser.getIsNeedRegisterMember() != 1){
+                    if(companyUser != null &&
+                            (companyUser.getIsAllowedAllRegister() == null || companyUser.getIsAllowedAllRegister() == 1)
+                            && companyUser.getIsNeedRegisterMember() != null && companyUser.getIsNeedRegisterMember() != 1){
                         user.setCompanyId(param.getCompanyId());
                         user.setCompanyUserId(param.getCompanyUserId());
                     }
@@ -183,7 +185,9 @@ public class WxCompanyUserController extends AppBaseController {
                     user.setUnionId(session.getUnionid());
                     user.setCreateTime(new Date());
                     user.setPhone(phoneNoInfo.getPhoneNumber());
-                    if(companyUser != null && companyUser.getIsNeedRegisterMember() != null && companyUser.getIsNeedRegisterMember() != 1){
+                    if(companyUser != null &&
+                            (companyUser.getIsAllowedAllRegister() == null || companyUser.getIsAllowedAllRegister() == 1)
+                            && companyUser.getIsNeedRegisterMember() != null && companyUser.getIsNeedRegisterMember() != 1){
                         user.setCompanyId(param.getCompanyId());
                         user.setCompanyUserId(param.getCompanyUserId());
                     }

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

@@ -103,7 +103,7 @@ public class WxH5MpController {
                 user.setMpOpenId(wxMpUser.getOpenid());
                 user.setUnionId(wxMpUser.getUnionId());
                 user.setCreateTime(new Date());
-                if(companyUser.getIsNeedRegisterMember() != 1){
+                if((companyUser.getIsAllowedAllRegister() == null || companyUser.getIsAllowedAllRegister() != 0) && companyUser.getIsNeedRegisterMember() != 1){
                     user.setCompanyId(param.getCompanyId());
                     user.setCompanyUserId(param.getCompanyUserId());
                 }