Переглянути джерело

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

caoliqin 1 місяць тому
батько
коміт
1f49ad8bc1
29 змінених файлів з 1005 додано та 40 видалено
  1. 18 5
      fs-admin/src/main/java/com/fs/api/controller/IndexStatisticsController.java
  2. 2 2
      fs-admin/src/main/java/com/fs/core/config/DataSourceConfig.java
  3. 1 0
      fs-admin/src/main/java/com/fs/core/datasource/DynamicDataSourceContextHolder.java
  4. 22 0
      fs-admin/src/main/java/com/fs/course/controller/FsCourseQuestionBankController.java
  5. 7 0
      fs-admin/src/main/java/com/fs/course/controller/FsUserCourseVideoController.java
  6. 225 0
      fs-admin/src/main/java/com/fs/qw/controller/QwSopController.java
  7. 78 4
      fs-admin/src/main/java/com/fs/qw/controller/QwSopTempController.java
  8. 2 2
      fs-company/src/main/resources/application.yml
  9. 2 2
      fs-qw-task/src/main/resources/application.yml
  10. 1 1
      fs-service-system/src/main/java/com/fs/course/domain/FsCourseQuestionBank.java
  11. 12 0
      fs-service-system/src/main/java/com/fs/course/domain/FsUserCourseVideo.java
  12. 26 0
      fs-service-system/src/main/java/com/fs/course/dto/FsCourseQuestionBankImportDTO.java
  13. 9 0
      fs-service-system/src/main/java/com/fs/course/mapper/FsUserCourseCategoryMapper.java
  14. 2 0
      fs-service-system/src/main/java/com/fs/course/mapper/FsUserCourseVideoMapper.java
  15. 23 0
      fs-service-system/src/main/java/com/fs/course/param/CourseVideoUpdates.java
  16. 10 0
      fs-service-system/src/main/java/com/fs/course/service/IFsCourseQuestionBankService.java
  17. 1 0
      fs-service-system/src/main/java/com/fs/course/service/IFsUserCourseVideoService.java
  18. 123 1
      fs-service-system/src/main/java/com/fs/course/service/impl/FsCourseQuestionBankServiceImpl.java
  19. 5 0
      fs-service-system/src/main/java/com/fs/course/service/impl/FsUserCourseVideoServiceImpl.java
  20. 10 0
      fs-service-system/src/main/java/com/fs/course/vo/FsUserCourseVideoQVO.java
  21. 1 1
      fs-service-system/src/main/java/com/fs/sop/domain/QwSop.java
  22. 4 1
      fs-service-system/src/main/java/com/fs/sop/domain/QwSopTemp.java
  23. 2 0
      fs-service-system/src/main/java/com/fs/sop/service/IQwSopTempService.java
  24. 88 0
      fs-service-system/src/main/java/com/fs/sop/service/impl/QwSopTempServiceImpl.java
  25. 21 14
      fs-service-system/src/main/java/com/fs/statis/StatisticsRedisConstant.java
  26. 9 2
      fs-service-system/src/main/java/com/fs/statis/service/IStatisticsService.java
  27. 277 4
      fs-service-system/src/main/java/com/fs/statis/service/impl/StatisticsServiceImpl.java
  28. 19 1
      fs-service-system/src/main/resources/mapper/course/FsUserCourseVideoMapper.xml
  29. 5 0
      fs-service-system/src/main/resources/mapper/sop/QwSopTempMapper.xml

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

@@ -10,9 +10,10 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
 import com.fs.common.core.domain.R;
 
+import java.util.ArrayList;
 import java.util.List;
 
-import static com.fs.statis.StatisticsRedisConstant.DATA_OVERVIEW_DEALER_CHARTS;
+import static com.fs.statis.StatisticsRedisConstant.*;
 
 /**
  * 首页-统计
@@ -76,7 +77,13 @@ public class IndexStatisticsController {
      */
     @PostMapping("/deaMemberTopTen")
     public R deaMemberTopTen(@RequestBody AnalysisPreviewQueryDTO param){
-        List<DeaMemberTopTenDTO> deaMemberTopTenDTOS = statisticsService.deaMemberTopTen(param);
+        Integer type = param.getType();
+        Integer statisticalType = param.getStatisticalType();
+
+        List<DeaMemberTopTenDTO> deaMemberTopTenDTOS = redisCache.getCacheObject(String.format("%s::%d::%d", CHARTS_MEMBER_TOP_TEN_WATCH, type, statisticalType));
+        if(deaMemberTopTenDTOS == null){
+            deaMemberTopTenDTOS = new ArrayList<>();
+        }
         return R.ok().put("data", deaMemberTopTenDTOS);
     }
 
@@ -85,7 +92,9 @@ public class IndexStatisticsController {
      */
     @PostMapping("/rewardMoneyTopTen")
     public R rewardMoneyTopTen(@RequestBody AnalysisPreviewQueryDTO param){
-        List<RewardMoneyTopTenDTO> rewardMoneyTopTenDTOS = statisticsService1.rewardMoneyTopTen(param);
+        Integer type = param.getType();
+        Integer dataType = param.getDataType();
+        List<RewardMoneyTopTenDTO> rewardMoneyTopTenDTOS = redisCache.getCacheObject( String.format("%s::%d::%d", CHARTS_REWARD_MONEY_TOP_TEN, type,dataType));
         return R.ok().put("data", rewardMoneyTopTenDTOS);
     }
 
@@ -94,7 +103,8 @@ public class IndexStatisticsController {
      */
     @PostMapping("/rewardMoneyTrend")
     public R rewardMoneyTrend(@RequestBody AnalysisPreviewQueryDTO param){
-        List<RewardMoneyTrendDTO> rewardMoneyTrendDTOS = statisticsService1.rewardMoneyTrendDTO(param);
+        Integer type = param.getType();
+        List<RewardMoneyTrendDTO> rewardMoneyTrendDTOS = redisCache.getCacheObject( String.format("%s::%d", CHARTS_REWARD_MONEY_TREND, type));
         return R.ok().put("data", rewardMoneyTrendDTOS);
     }
 
@@ -103,7 +113,10 @@ public class IndexStatisticsController {
      */
     @PostMapping("/watchCourseTopTen")
     public R watchCourseTopTen(@RequestBody AnalysisPreviewQueryDTO param){
-        List<CourseStatsDTO> courseStatsDTOS = statisticsService1.watchCourseTopTen(param);
+        Integer type = param.getType();
+        String sort = param.getSort();
+        Integer statisticalType = param.getStatisticalType();
+        List<CourseStatsDTO> courseStatsDTOS = redisCache.getCacheObject(String.format("%s::%d::%d::%s", CHARTS_WATCH_TOP_TEN, type,statisticalType,sort));
         return R.ok().put("data", courseStatsDTOS);
     }
 

+ 2 - 2
fs-admin/src/main/java/com/fs/core/config/DataSourceConfig.java

@@ -48,9 +48,9 @@ public class DataSourceConfig {
                                         @Qualifier("sopDataSource") DataSource sopDataSource,
                                         @Qualifier("slaveDataSource") DataSource slaveDataSource) {
         Map<Object, Object> targetDataSources = new HashMap<>();
-        targetDataSources.put(DataSourceType.MASTER, masterDataSource);
+        targetDataSources.put(DataSourceType.MASTER.name(), masterDataSource);
 
-        targetDataSources.put(DataSourceType.SLAVE, slaveDataSource);
+        targetDataSources.put(DataSourceType.SLAVE.name(), slaveDataSource);
         targetDataSources.put(DataSourceType.SOP.name(), sopDataSource);
         return new DynamicDataSource(masterDataSource, targetDataSources);
     }

+ 1 - 0
fs-admin/src/main/java/com/fs/core/datasource/DynamicDataSourceContextHolder.java

@@ -40,6 +40,7 @@ public class DynamicDataSourceContextHolder
      */
     public static void clearDataSourceType()
     {
+        log.info("清除当前{}数据源", getDataSourceType());
         CONTEXT_HOLDER.remove();
     }
 }

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

@@ -11,11 +11,14 @@ 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.FsCourseQuestionBank;
+import com.fs.course.dto.FsCourseQuestionBankImportDTO;
 import com.fs.course.service.IFsCourseQuestionBankService;
 
+import com.fs.store.dto.StoreOrderExpressExportDTO;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
 
 import java.util.List;
 
@@ -106,4 +109,23 @@ public class FsCourseQuestionBankController extends BaseController
         return toAjax(fsCourseQuestionBankService.deleteFsCourseQuestionBankByIds(ids));
     }
 
+    //下载模板
+    @GetMapping("/importTemplate")
+    public AjaxResult importTemplate() {
+        ExcelUtil<FsCourseQuestionBankImportDTO> util = new ExcelUtil<>(FsCourseQuestionBankImportDTO.class);
+        return util.importTemplateExcel("课程题目数据");
+    }
+
+    @Log(title = "导入", businessType = BusinessType.IMPORT)
+    @PreAuthorize("@ss.hasPermi('course:courseQuestionBank:importData')")
+    @PostMapping("/importData")
+    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());
+        return AjaxResult.success(message);
+    }
+
 }

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

@@ -9,6 +9,7 @@ import com.fs.common.enums.BusinessType;
 import com.fs.common.utils.poi.ExcelUtil;
 import com.fs.course.domain.FsUserCourseVideo;
 import com.fs.course.mapper.FsUserCourseVideoMapper;
+import com.fs.course.param.CourseVideoUpdates;
 import com.fs.course.service.IFsUserCourseVideoService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
@@ -118,4 +119,10 @@ public class FsUserCourseVideoController extends BaseController
     {
         return R.ok().put("data",fsUserCourseVideoService.selectCourseVideoSort(courseId));
     }
+
+    @PostMapping("/updates")
+    public R updates(@RequestBody CourseVideoUpdates vo){
+        fsUserCourseVideoService.updates(vo);
+        return R.ok();
+    }
 }

+ 225 - 0
fs-admin/src/main/java/com/fs/qw/controller/QwSopController.java

@@ -0,0 +1,225 @@
+package com.fs.qw.controller;
+
+import com.fs.common.annotation.Log;
+import com.fs.common.annotation.RepeatSubmit;
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.core.domain.R;
+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.mapper.FsUserCourseMapper;
+import com.fs.course.mapper.FsUserCourseVideoMapper;
+import com.fs.his.vo.OptionsVO;
+import com.fs.qw.domain.QwSopUpdateStatus;
+import com.fs.qw.service.IQwUserService;
+import com.fs.sop.domain.QwSop;
+import com.fs.sop.params.QwSopAutoTime;
+import com.fs.sop.params.QwSopEditQwUserParam;
+import com.fs.sop.service.IQwSopService;
+import com.fs.sop.vo.SopVoiceListVo;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import java.io.IOException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * 企微sopController
+ *
+ * @author fs
+ * @date 2024-07-31
+ */
+@RestController
+@RequestMapping("/qw/sop")
+public class QwSopController extends BaseController
+{
+    @Autowired
+    private IQwSopService qwSopService;
+
+    @Autowired
+    private IQwUserService qwUserService;
+    @Autowired
+    private TokenService tokenService;
+
+    @Autowired
+    private FsUserCourseMapper fsUserCourseMapper;
+    @Autowired
+    private FsUserCourseVideoMapper fsUserCourseVideoMapper;
+    /**
+     * 查询企微sop列表
+     */
+    @PreAuthorize("@ss.hasPermi('qw:sop:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(QwSop qwSop)
+    {
+        startPage();
+        List<QwSop> list = qwSopService.selectQwSopList(qwSop);
+        return getDataTable(list);
+    }
+
+    /**
+     * 查询aiChatsop列表
+     */
+    @GetMapping("/listAiChatSop")
+    public TableDataInfo listAiChatSop(QwSop qwSop)
+    {
+        startPage();
+        List<QwSop> list = qwSopService.selectAiChatQwSopList(qwSop);
+        return getDataTable(list);
+    }
+    @GetMapping("/courseList")
+    public R courseList()
+    {
+        List<OptionsVO> optionsVOS = fsUserCourseMapper.selectFsUserCourseAllList();
+        return R.ok().put("list", optionsVOS);
+    }
+
+    @GetMapping(value = "/videoList/{id}")
+    public R videoList(@PathVariable("id") Long id)
+    {
+        List<OptionsVO> optionsVOS = fsUserCourseVideoMapper.selectFsUserCourseVodeAllList(id);
+        return R.ok().put("list", optionsVOS);
+    }
+    /**
+     * 查询企微sop列表-我的
+     */
+    @PreAuthorize("@ss.hasPermi('qw:sop:myList')")
+    @GetMapping("/myList")
+    public TableDataInfo myList(QwSop qwSop)
+    {
+        startPage();
+        List<QwSop> list = qwSopService.selectQwSopMyList(qwSop);
+        return getDataTable(list);
+    }
+    /**
+     * 导出企微sop列表
+     */
+    @PreAuthorize("@ss.hasPermi('qw:sop:export')")
+    @Log(title = "企微sop", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(QwSop qwSop)
+    {
+        List<QwSop> list = qwSopService.selectQwSopList(qwSop);
+        ExcelUtil<QwSop> util = new ExcelUtil<QwSop>(QwSop.class);
+        return util.exportExcel(list, "企微sop数据");
+    }
+
+    /**
+     * 获取企微sop详细信息
+     */
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") String id)
+    {
+        return AjaxResult.success(qwSopService.selectQwSopById(id));
+    }
+
+    /**
+     * 新增企微sop
+     */
+    @PreAuthorize("@ss.hasPermi('qw:sop:add')")
+    @Log(title = "企微sop", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody QwSop qwSop)
+    {
+        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        qwSop.setCreateBy(loginUser.getUser().getNickName());
+        qwSop.setCreateTime(sdf.format(new Date()));
+
+        return toAjax(qwSopService.insertQwSop(qwSop));
+
+    }
+
+    /**
+     * 修改企微sop
+     */
+    @PreAuthorize("@ss.hasPermi('qw:sop:edit')")
+    @Log(title = "修改企微sop", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public R edit(@RequestBody QwSop qwSop)
+    {
+        return qwSopService.updateQwSop(qwSop);
+    }
+
+
+    /**
+     * 暂停企微sop
+     */
+    @Log(title = "暂停企微sop", businessType = BusinessType.UPDATE)
+    @PostMapping("/updateSopStatus")
+    @RepeatSubmit
+    public R  updateSopStatus(@RequestBody QwSopUpdateStatus param)
+    {
+        return qwSopService.updateSopStatus(param);
+    }
+
+    /**
+     * 修改企微sop自动创建时间
+     */
+    @Log(title = "企微sop自动创建时间", businessType = BusinessType.UPDATE)
+    @PostMapping("/updateAutoSopTime")
+    @RepeatSubmit
+    public AjaxResult updateAutoSopTime(@RequestBody QwSopAutoTime param)
+    {
+        return toAjax(qwSopService.updateAutoSopTime(param));
+    }
+
+    /**
+     * 删除企微sop
+     */
+    @PreAuthorize("@ss.hasPermi('qw:sop:remove')")
+    @Log(title = "企微sop", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable String[] ids)
+    {
+        return toAjax(qwSopService.deleteQwSopByIds(ids));
+    }
+
+
+    /**
+     * 批量执行SOP
+     */
+    @GetMapping(value = "/updateStatus/{ids}")
+    public R batchDoSop(@PathVariable String[] ids)
+    {
+        return qwSopService.updateStatusQwSopByIds(ids);
+    }
+
+    /**
+     * 修改sop员工
+     */
+    @PostMapping( "/updateSopQwUser")
+    @Log(title = "修改sop员工", businessType = BusinessType.UPDATE)
+    @PreAuthorize("@ss.hasPermi('qw:sop:updateSopQwUser')")
+    public R updateSopQwUser(@RequestBody QwSopEditQwUserParam param)
+    {
+        return qwSopService.updateSopQwUser(param);
+    }
+
+    /**
+    * 服务器图片地址 转 企业微信地址
+    */
+    @PostMapping(value = "/updateMediaImage")
+    public R updateMediaImage(@RequestParam("url") String url) throws IOException {
+
+        String  cropId=null;
+        return qwSopService.updateMediaImage(url,cropId);
+    }
+    /**
+    * 服务器图片地址 转 企业微信地址
+    */
+    @GetMapping(value = "/getSopVoiceList")
+    public TableDataInfo getSopVoiceList(String id) {
+        startPage();
+        List<SopVoiceListVo> list = qwSopService.getSopVoiceList(id);
+        return getDataTable(list);
+    }
+}

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

@@ -5,8 +5,14 @@ import com.fs.common.core.controller.BaseController;
 import com.fs.common.core.domain.AjaxResult;
 import com.fs.common.core.page.TableDataInfo;
 import com.fs.common.enums.BusinessType;
+import com.fs.common.utils.ServletUtils;
 import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.core.security.LoginUser;
+import com.fs.core.web.service.TokenService;
+import com.fs.qw.vo.SortDayVo;
 import com.fs.sop.domain.QwSopTemp;
+import com.fs.sop.domain.QwSopTempDay;
+import com.fs.sop.params.QwSopShareTempParam;
 import com.fs.sop.service.IQwSopTempService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
@@ -28,14 +34,18 @@ public class QwSopTempController extends BaseController
 {
     @Autowired
     private IQwSopTempService qwSopTempService;
+    @Autowired
+    private TokenService tokenService;
     /**
      * 查询sop模板列表
      */
+    @PreAuthorize("@ss.hasPermi('qw:sopTemp:list')")
     @GetMapping("/list")
     public TableDataInfo list(QwSopTemp qwSopTemp)
     {
         startPage();
-        List<QwSopTemp> list = qwSopTempService.selectQwSopTempList(qwSopTemp);
+//        List<QwSopTemp> list = qwSopTempService.selectQwSopTempList(qwSopTemp);
+        List<QwSopTemp> list = qwSopTempService.selectQwSopTempListNew(qwSopTemp);
         return getDataTable(list);
     }
 
@@ -60,15 +70,13 @@ public class QwSopTempController extends BaseController
     {
         return AjaxResult.success(qwSopTempService.selectQwSopTempById(id));
     }
-
     /**
      * 新增sop模板
      */
     @PreAuthorize("@ss.hasPermi('qw:sopTemp:add')")
     @Log(title = "sop模板", businessType = BusinessType.INSERT)
     @PostMapping
-    public AjaxResult add(@RequestBody QwSopTemp qwSopTemp)
-    {
+    public AjaxResult add(@RequestBody QwSopTemp qwSopTemp){
         return toAjax(qwSopTempService.insertQwSopTemp(qwSopTemp));
     }
 
@@ -99,4 +107,70 @@ public class QwSopTempController extends BaseController
 //        qwSopTempService.deleteQwSopTempByIds(ids);
         return toAjax(qwSopTempService.updateQwSopTempByIds(ids));
     }
+
+    /** 分享sop模板 */
+    @PreAuthorize("@ss.hasPermi('qw:sopTemp:share')")
+    @Log(title = "分享sop模板", businessType = BusinessType.DELETE)
+    @PostMapping("/shareTemp")
+    public AjaxResult shareTemp(@RequestBody QwSopShareTempParam param)
+    {
+        return toAjax(qwSopTempService.shareQwSopTemp(param));
+    }
+
+
+
+    @PreAuthorize("@ss.hasPermi('qw:sopTemp:add')")
+    @Log(title = "sop模板", businessType = BusinessType.INSERT)
+    @PostMapping("/add")
+    public AjaxResult addNew(@RequestBody QwSopTemp qwSopTemp){
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        qwSopTemp.setCreateBy(loginUser.getUser().getUserId().toString());
+        int i = qwSopTempService.addNew(qwSopTemp);
+        if(qwSopTemp.getSendType() == 5){
+            qwSopTempService.createSopTempRules(qwSopTemp);
+        }
+        return toAjax(i);
+    }
+    @PreAuthorize("@ss.hasPermi('qw:sopTemp:edit')")
+    @Log(title = "sop模板", businessType = BusinessType.UPDATE)
+    @PostMapping("/update")
+    public AjaxResult updateNew(@RequestBody QwSopTemp qwSopTemp){
+        int update = qwSopTempService.update(qwSopTemp);
+        return toAjax(update);
+    }
+    @PreAuthorize("@ss.hasPermi('qw:sopTemp:edit')")
+    @Log(title = "sop模板规则", businessType = BusinessType.UPDATE)
+    @PostMapping("/addOrUpdateSetting")
+    public AjaxResult addOrUpdateSetting(@RequestBody QwSopTempDay day){
+        return AjaxResult.success(qwSopTempService.addOrUpdateSetting(day));
+    }
+    @PreAuthorize("@ss.hasPermi('qw:sopTemp:edit')")
+    @Log(title = "sop模板规则", businessType = BusinessType.DELETE)
+    @GetMapping("/delRules")
+    public AjaxResult delRules(Long id){
+        qwSopTempService.delRules(id);
+        return toAjax(1);
+    }
+    @PreAuthorize("@ss.hasPermi('qw:sopTemp:list')")
+    @GetMapping("/selectRulesInfo")
+    public AjaxResult selectRulesInfo(Long id){
+        return AjaxResult.success(qwSopTempService.selectRulesInfo(id));
+    }
+    @PreAuthorize("@ss.hasPermi('qw:sopTemp:edit')")
+    @PostMapping("/copyTemplate")
+    public AjaxResult copyTemplate(@RequestBody QwSopTemp qwSopTemp){
+        qwSopTempService.copyTemplate(qwSopTemp);
+        return toAjax(1);
+    }
+    @PreAuthorize("@ss.hasPermi('qw:sopTemp:edit')")
+    @PostMapping("/sortDay")
+    public AjaxResult sortDay(@RequestBody List<SortDayVo> list){
+        qwSopTempService.sortDay(list);
+        return toAjax(1);
+    }
+    @PreAuthorize("@ss.hasPermi('qw:sopTemp:edit')")
+    @GetMapping("/dayList")
+    public AjaxResult dayList(String id){
+        return AjaxResult.success(qwSopTempService.dayList(id));
+    }
 }

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

@@ -43,8 +43,8 @@ spring:
     # 国际化资源文件路径
     basename: i18n/messages
   profiles:
-#    active: dev
-    active: druid
+    active: dev
+#    active: druid
     include: config
   # 文件上传
   servlet:

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

@@ -43,8 +43,8 @@ spring:
     # 国际化资源文件路径
     basename: i18n/messages
   profiles:
-    active: druid
-#    active: dev
+#    active: druid
+    active: dev
     include: config
   # 文件上传
   servlet:

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

@@ -41,5 +41,5 @@ public class FsCourseQuestionBank extends BaseEntity
     /** 答案 */
     @Excel(name = "答案")
     private String answer;
-    private String questionType;
+    private Long questionType;
 }

+ 12 - 0
fs-service-system/src/main/java/com/fs/course/domain/FsUserCourseVideo.java

@@ -1,9 +1,12 @@
 package com.fs.course.domain;
 
+import com.fasterxml.jackson.annotation.JsonFormat;
 import com.fs.common.annotation.Excel;
 import com.fs.common.core.domain.BaseEntity;
 import lombok.Data;
 
+import java.time.LocalTime;
+
 /**
  * 课堂视频对象 fs_user_course_video
  *
@@ -85,4 +88,13 @@ public class FsUserCourseVideo extends BaseEntity
 
     private String transcodeFileKey;//转码的文件key
 
+    @JsonFormat(pattern = "HH:mm:ss")
+    private LocalTime viewStartTime;//转码的文件key
+
+    @JsonFormat(pattern = "HH:mm:ss")
+    private LocalTime viewEndTime;//转码的文件key
+
+    @JsonFormat(pattern = "HH:mm:ss")
+    private LocalTime lastJoinTime;//转码的文件key
+
 }

+ 26 - 0
fs-service-system/src/main/java/com/fs/course/dto/FsCourseQuestionBankImportDTO.java

@@ -0,0 +1,26 @@
+package com.fs.course.dto;
+
+import com.fs.common.annotation.Excel;
+import lombok.Data;
+
+@Data
+public class FsCourseQuestionBankImportDTO {
+
+    @Excel(name = "标题")
+    private String title;
+
+    @Excel(name = "问题类别")
+    private String questionType;
+
+    @Excel(name = "题目类型: 单选 多选")
+    private String type;
+
+    @Excel(name = "选项: 多个用 | 隔开")
+    private String question;
+
+    @Excel(name = "答案: 多个用 | 隔开")
+    private String answer;
+
+    @Excel(name = "序号")
+    private long sort;
+}

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

@@ -3,6 +3,7 @@ package com.fs.course.mapper;
 import java.util.List;
 import com.fs.course.domain.FsUserCourseCategory;
 import com.fs.his.vo.OptionsVO;
+import org.apache.ibatis.annotations.Param;
 import org.apache.ibatis.annotations.Select;
 
 /**
@@ -69,4 +70,12 @@ public interface FsUserCourseCategoryMapper
 
     @Select("select cate_id dict_value, cate_name dict_label  from fs_user_course_category WHERE pid =#{pid} and is_del=0 ")
     List<OptionsVO> selectCateListByPid(Long pid);
+
+    /**
+     * 根据名称查询分类
+     * @param name  名称
+     * @return  FsUserCourseCategory
+     */
+    @Select("select * from fs_user_course_category where cate_name = #{name} limit 1")
+    FsUserCourseCategory selectFsUserCourseCategoryByName(@Param("name")String name);
 }

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

@@ -4,6 +4,7 @@ import java.util.List;
 import java.util.Map;
 
 import com.fs.course.domain.FsUserCourseVideo;
+import com.fs.course.param.CourseVideoUpdates;
 import com.fs.course.param.FsUserCourseVideoListUParam;
 import com.fs.course.param.FsUserCourseVideoParam;
 import com.fs.course.param.newfs.UserCourseVideoPageParam;
@@ -166,4 +167,5 @@ public interface FsUserCourseVideoMapper
 
     List<FsUserCourseVideoPageListVO> selectFsUserCourseVideoPageList(UserCourseVideoPageParam param);
 
+    void updates(CourseVideoUpdates vo);
 }

+ 23 - 0
fs-service-system/src/main/java/com/fs/course/param/CourseVideoUpdates.java

@@ -0,0 +1,23 @@
+package com.fs.course.param;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.Data;
+
+import java.time.LocalTime;
+import java.util.List;
+
+@Data
+public class CourseVideoUpdates {
+
+    private List<Long> ids;
+
+    @JsonFormat(pattern = "HH:mm:ss")
+    private LocalTime viewStartTime;//转码的文件key
+
+    @JsonFormat(pattern = "HH:mm:ss")
+    private LocalTime viewEndTime;//转码的文件key
+
+    @JsonFormat(pattern = "HH:mm:ss")
+    private LocalTime lastJoinTime;//转码的文件key
+
+}

+ 10 - 0
fs-service-system/src/main/java/com/fs/course/service/IFsCourseQuestionBankService.java

@@ -2,8 +2,10 @@ package com.fs.course.service;
 
 import com.fs.common.core.domain.R;
 import com.fs.course.domain.FsCourseQuestionBank;
+import com.fs.course.dto.FsCourseQuestionBankImportDTO;
 import com.fs.course.param.FsCourseQuestionAnswerUParam;
 
+import javax.validation.constraints.Size;
 import java.util.List;
 
 /**
@@ -73,4 +75,12 @@ public interface IFsCourseQuestionBankService
      */
     R courseAnswerByfsUser(FsCourseQuestionAnswerUParam param);
 
+    /**
+     * 题目导入
+     *
+     * @param list     数据
+     * @param nickName 昵称
+     * @return String
+     */
+    String importData(List<FsCourseQuestionBankImportDTO> list, @Size String nickName);
 }

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

@@ -144,4 +144,5 @@ public interface IFsUserCourseVideoService
      */
     R updateWatchDurationWx(FsUserCourseVideoUParam param);
 
+    void updates(CourseVideoUpdates vo);
 }

+ 123 - 1
fs-service-system/src/main/java/com/fs/course/service/impl/FsCourseQuestionBankServiceImpl.java

@@ -1,24 +1,28 @@
 package com.fs.course.service.impl;
 
 import cn.hutool.json.JSONUtil;
+import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import com.fs.common.core.domain.R;
+import com.fs.common.exception.ServiceException;
 import com.fs.common.utils.DateUtils;
 import com.fs.common.utils.StringUtils;
 import com.fs.course.config.CourseConfig;
 import com.fs.course.domain.*;
+import com.fs.course.dto.FsCourseQuestionBankImportDTO;
 import com.fs.course.mapper.*;
 import com.fs.course.param.FsCourseQuestionAnswerUParam;
 import com.fs.course.service.IFsCourseQuestionBankService;
 import com.fs.store.domain.FsUser;
 import com.fs.store.mapper.FsUserMapper;
-import com.fs.store.param.WxSendRedPacketParam;
 import com.fs.store.service.IFsStorePaymentService;
 import com.fs.system.service.ISysConfigService;
+import com.hc.openapi.tool.fastjson.JSON;
 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.stream.Collectors;
 
@@ -49,6 +53,8 @@ public class FsCourseQuestionBankServiceImpl implements IFsCourseQuestionBankSer
     private FsUserCourseVideoMapper courseVideoMapper;
     @Autowired
     private FsCourseWatchLogMapper courseWatchLogMapper;
+    @Autowired
+    private FsUserCourseCategoryMapper courseCategoryMapper;
 
     /**
      * 查询题库
@@ -331,6 +337,122 @@ public class FsCourseQuestionBankServiceImpl implements IFsCourseQuestionBankSer
         }
     }
 
+    /**
+     * 题目导入
+     *
+     * @param list     数据
+     * @param nickName 昵称
+     * @return String
+     */
+    @Override
+    public String importData(List<FsCourseQuestionBankImportDTO> list, @Size String nickName) {
+        if (Objects.isNull(list) || list.isEmpty()) {
+            throw new ServiceException("导入数据不能为空");
+        }
+
+        int successNum = 0;
+        int failureNum = 0;
+        StringBuilder importSuccessMsg = new StringBuilder();
+        StringBuilder importErrorMsg = new StringBuilder();
+        StringBuilder importMsg = new StringBuilder();
+
+        for (FsCourseQuestionBankImportDTO importDTO : list) {
+            try {
+                String title = importDTO.getTitle();
+                String type = importDTO.getType();
+                String questionType = importDTO.getQuestionType();
+                String question = importDTO.getQuestion();
+                String answer = importDTO.getAnswer();
+
+                if (StringUtils.isBlank(title) || StringUtils.isBlank(type) || StringUtils.isBlank(question) || StringUtils.isBlank(answer)) {
+                    String msg = "<br/>" + failureNum + "、题目 " + title + " 导入失败:信息不完整";
+                    importErrorMsg.append(msg);
+                    failureNum++;
+                    continue;
+                }
+
+                if (!type.contains("单") && !type.contains("多")) {
+                    String msg = "<br/>" + failureNum + "、题目 " + title + " 导入失败:题目类型不正确";
+                    importErrorMsg.append(msg);
+                    failureNum++;
+                    continue;
+                }
+
+                // 判断答案是否在选项里
+                String[] questions = question.split("\\|");
+                String[] answers = answer.split("\\|");
+
+                if (type.contains("多") && answers.length < 2) {
+                    String msg = "<br/>" + failureNum + "、题目 " + title + " 导入失败:多选题答案不能少于2个";
+                    importErrorMsg.append(msg);
+                    failureNum++;
+                    continue;
+                }
+
+                List<String> optionsList = Arrays.asList(questions);
+                boolean allAnswersInOptions = true;
+
+                // 遍历每一个正确答案文本
+                for (String correctAnswer : answers) {
+                    // 检查当前正确答案文本是否存在于选项列表中
+                    if (!optionsList.contains(correctAnswer.trim())) {
+                        allAnswersInOptions = false; // 发现一个不在选项里的答案
+                        break;
+                    }
+                }
+
+                if (!allAnswersInOptions) {
+                    String msg = "<br/>" + failureNum + "、题目 " + title + " 导入失败:答案不在选项中";
+                    importErrorMsg.append(msg);
+                    failureNum++;
+                    continue;
+                }
+
+                JSONArray questionArray = new JSONArray();
+                optionsList = Arrays.asList(answers);
+                for (int i = 0; i < questions.length; i++) {
+                    JSONObject optionObj = new JSONObject();
+                    optionObj.put("name", questions[i]);
+                    optionObj.put("isAnswer", optionsList.contains(questions[i].trim()) ? 1 : 0);
+                    optionObj.put("indexId", i);
+                    questionArray.add(optionObj);
+                }
+
+                // 分类
+                Long questionTypeId = null;
+                FsUserCourseCategory category = courseCategoryMapper.selectFsUserCourseCategoryByName(questionType);
+                if (Objects.nonNull(category)) {
+                    questionTypeId = category.getCateId();
+                }
+
+                FsCourseQuestionBank questionBank = new FsCourseQuestionBank();
+                questionBank.setTitle(title);
+                questionBank.setType(type.contains("单") ? 1L : 2L);
+                questionBank.setQuestionType(questionTypeId);
+                questionBank.setStatus(1L);
+                questionBank.setSort(importDTO.getSort());
+                questionBank.setQuestion(JSON.toJSONString(questionArray));
+                questionBank.setAnswer(answers.length > 1 ? JSON.toJSONString(answers) : answer);
+                questionBank.setCreateTime(new Date());
+                questionBank.setCreateBy(nickName);
+                fsCourseQuestionBankMapper.insertFsCourseQuestionBank(questionBank);
+
+                importSuccessMsg.append("<br/>").append(successNum).append("、题目 ").append(title).append(" 导入成功");
+                successNum++;
+            } catch (Exception e) {
+                String msg = "<br/>" + failureNum + "、题目 " + importDTO.getTitle() + " 导入异常:";
+                importErrorMsg.append(msg).append(e.getMessage());
+                failureNum++;
+            }
+        }
+
+        // 在所有导入处理完成后,构建最终的导入结果消息
+        importMsg.insert(0, "导入完成!成功" + successNum + " 条,失败" + failureNum + "条。");
+        importMsg.append(importErrorMsg);
+        importMsg.append(importSuccessMsg);
+        return importMsg.toString();
+    }
+
 
     public static String[] convertStringToArray(String inputString) {
         String cleanString = inputString.replaceAll("[\\[\\]\"\\s]", "");

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

@@ -1014,6 +1014,11 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
         }
     }
 
+    @Override
+    public void updates(CourseVideoUpdates vo) {
+        fsUserCourseVideoMapper.updates(vo);
+    }
+
     //会员-更新心跳时间
     public void updateHeartbeatWx(FsUserCourseVideoUParam param) {
         String redisKey = "h5wxuser:watch:heartbeat:" + param.getUserId() + ":" + param.getVideoId();

+ 10 - 0
fs-service-system/src/main/java/com/fs/course/vo/FsUserCourseVideoQVO.java

@@ -1,10 +1,12 @@
 package com.fs.course.vo;
 
+import com.fasterxml.jackson.annotation.JsonFormat;
 import com.fs.common.annotation.Excel;
 import com.fs.common.core.domain.BaseEntity;
 import com.fs.course.domain.FsCourseQuestionBank;
 import lombok.Data;
 
+import java.time.LocalTime;
 import java.util.List;
 
 /**
@@ -82,4 +84,12 @@ public class FsUserCourseVideoQVO extends BaseEntity {
 
     private String packageJson;
     private Integer isFirst;
+    @JsonFormat(pattern = "HH:mm:ss")
+    private LocalTime viewStartTime;//转码的文件key
+
+    @JsonFormat(pattern = "HH:mm:ss")
+    private LocalTime viewEndTime;//转码的文件key
+
+    @JsonFormat(pattern = "HH:mm:ss")
+    private LocalTime lastJoinTime;//转码的文件key
 }

+ 1 - 1
fs-service-system/src/main/java/com/fs/sop/domain/QwSop.java

@@ -123,7 +123,7 @@ public class QwSop implements Serializable {
     private Integer courseDateNum;
     // 新课对话模板
     private String newTemplateId;
-    private String project;
+    private Long project;
     // 群聊ID
     private String chatId;
 

+ 4 - 1
fs-service-system/src/main/java/com/fs/sop/domain/QwSopTemp.java

@@ -61,7 +61,8 @@ public class QwSopTemp implements Serializable
     private String updateTime;
 
     private String createBy;
-    private String project;
+    private Long project;
+    private Long courseId;
 
     @TableField(exist = false)
     private List<Map<String, Object>> rules;
@@ -69,5 +70,7 @@ public class QwSopTemp implements Serializable
     private boolean cuoser;
     @TableField(exist = false)
     private List<QwSopTempDay> list = new ArrayList<>();
+    @TableField(exist = false)
+    private List<String> timeList;
 
 }

+ 2 - 0
fs-service-system/src/main/java/com/fs/sop/service/IQwSopTempService.java

@@ -90,4 +90,6 @@ public interface IQwSopTempService
     void sortDay(List<SortDayVo> list);
 
     List<QwSopTempDay> dayList(String id);
+
+    void createSopTempRules(QwSopTemp qwSopTemp);
 }

+ 88 - 0
fs-service-system/src/main/java/com/fs/sop/service/impl/QwSopTempServiceImpl.java

@@ -7,8 +7,13 @@ import com.fs.common.annotation.DataSource;
 import com.fs.common.enums.DataSourceType;
 import com.fs.common.exception.base.BaseException;
 import com.fs.common.utils.PubFun;
+import com.fs.course.domain.FsUserCourse;
+import com.fs.course.domain.FsUserCourseVideo;
+import com.fs.course.mapper.FsUserCourseMapper;
+import com.fs.course.mapper.FsUserCourseVideoMapper;
 import com.fs.fastGpt.domain.FastGptChatReplaceWords;
 import com.fs.fastGpt.mapper.FastGptChatReplaceWordsMapper;
+import com.fs.qw.vo.QwSopTempSetting2;
 import com.fs.qw.vo.SortDayVo;
 import com.fs.sop.domain.QwSopTemp;
 import com.fs.sop.domain.QwSopTempContent;
@@ -21,10 +26,13 @@ import com.fs.sop.vo.VoiceVo;
 import lombok.AllArgsConstructor;
 import org.apache.rocketmq.spring.core.RocketMQTemplate;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
 
 import java.text.SimpleDateFormat;
 import java.time.LocalTime;
+import java.time.format.DateTimeFormatter;
 import java.util.*;
+import java.util.concurrent.atomic.AtomicInteger;
 import java.util.function.Consumer;
 import java.util.stream.Collectors;
 
@@ -45,6 +53,8 @@ public class QwSopTempServiceImpl implements IQwSopTempService
     private final IQwSopTempContentService qwSopTempContentService;
     private final IQwSopTempVoiceService qwSopTempVoiceService;
     private final RocketMQTemplate rocketMQTemplate;
+    private final FsUserCourseMapper fsUserCourseMapper;
+    private final FsUserCourseVideoMapper fsUserCourseVideoMapper;
 
     /**
      * 查询sop模板
@@ -56,6 +66,7 @@ public class QwSopTempServiceImpl implements IQwSopTempService
     public QwSopTemp selectQwSopTempById(String id){
 //        QwSopTemp qwSopTemp = qwSopTempMapper.selectQwSopTempById(id);
         QwSopTemp qwSopTemp = qwSopTempMapper.selectQwSopTempById(id);
+        if(qwSopTemp == null) return null;
         List<QwSopTempDay> qwSopTempDays = qwSopTempDayService.listByTempId(id);
         qwSopTemp.setList(qwSopTempDays);
 //        List<QwSopTempRules> rulesList = qwSopTempRulesService.listByTempId(id);
@@ -164,6 +175,7 @@ public class QwSopTempServiceImpl implements IQwSopTempService
         return qwSopTempMapper.deleteQwSopTempById(id);
     }
 
+
     @Override
     public int addNew(QwSopTemp qwSopTemp) {
         SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
@@ -172,6 +184,82 @@ public class QwSopTempServiceImpl implements IQwSopTempService
         return qwSopTempMapper.insertQwSopTemp(qwSopTemp);
     }
 
+    @Override
+    public void createSopTempRules(QwSopTemp temp) {
+        FsUserCourse fsUserCourse = fsUserCourseMapper.selectFsUserCourseByCourseId(temp.getCourseId());
+        temp.setProject(fsUserCourse.getProject());
+        qwSopTempMapper.updateQwSopTemp(temp);
+        List<FsUserCourseVideo> videoList = fsUserCourseVideoMapper.selectVideoByCourseId(fsUserCourse.getCourseId());
+        AtomicInteger i = new AtomicInteger(1);
+        Integer gap = temp.getGap();
+        List<QwSopTempDay> collect = videoList.stream().map(e -> {
+            QwSopTempDay day = new QwSopTempDay();
+            day.setTempId(temp.getId());
+            day.setDayNum(i.getAndIncrement() * gap);
+            day.setName("第" + day.getDayNum() + "天");
+            day.setSorts(day.getDayNum());
+            day.setList(new ArrayList<>());
+            QwSopTempRules rules = new QwSopTempRules();
+            rules.setTempId(temp.getId());
+            rules.setName(day.getName());
+            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH:mm");
+            rules.setTime(e.getViewStartTime().format(formatter));
+            rules.setContentType(2);
+            rules.setType(2);
+            rules.setCourseType(0);
+            rules.setCourseId(e.getCourseId());
+            rules.setVideoId(e.getVideoId());
+            rules.setSorts(0);
+            day.getList().add(rules);
+            QwSopTempContent content = new QwSopTempContent();
+            content.setTempId(temp.getId());
+            content.setContentType(3);
+            QwSopTempSetting2.Content.Setting setting = new QwSopTempSetting2.Content.Setting();
+            setting.setLinkTitle(fsUserCourse.getCourseName());
+            setting.setIsBindUrl(1);
+            setting.setLinkDescribe(e.getTitle());
+            setting.setLinkImageUrl(fsUserCourse.getImgUrl());
+            setting.setContentType("3");
+            content.setContent(JSON.toJSONString(setting));
+            content.setIsBindUrl(1);
+            rules.setList(Collections.singletonList(content));
+
+
+
+            if(temp.getTimeList() != null &&  !temp.getTimeList().isEmpty()){
+                AtomicInteger sorts = new AtomicInteger(1);
+                List<QwSopTempRules> rulesList = temp.getTimeList().stream().map(time -> {
+                    QwSopTempRules rulesSub = new QwSopTempRules();
+                    rulesSub.setTempId(temp.getId());
+                    rulesSub.setName(day.getName());
+                    rulesSub.setTime(time);
+                    rulesSub.setContentType(1);
+                    rulesSub.setType(1);
+                    rulesSub.setSorts(sorts.getAndIncrement());
+                    QwSopTempContent contentSbu = new QwSopTempContent();
+                    contentSbu.setTempId(temp.getId());
+                    contentSbu.setContentType(1);
+                    QwSopTempSetting2.Content.Setting settingSub = new QwSopTempSetting2.Content.Setting();
+                    settingSub.setContentType("1");
+                    settingSub.setValue("");
+                    contentSbu.setContent(JSON.toJSONString(settingSub));
+                    rulesSub.setList(Collections.singletonList(contentSbu));
+                    return rulesSub;
+                }).collect(Collectors.toList());
+                day.getList().addAll(rulesList);
+            }
+            return day;
+        }).collect(Collectors.toList());
+        qwSopTempDayService.addOrUpdateBatch(collect);
+        List<QwSopTempRules> ruleList = collect.stream().flatMap(e -> e.getList().stream().peek(r -> r.setDayId(e.getId()))).collect(Collectors.toList());
+        qwSopTempRulesService.saveList(ruleList);
+        List<QwSopTempContent> contentList = ruleList.stream().flatMap(e -> e.getList().stream().peek(r -> {
+            r.setDayId(e.getDayId());
+            r.setRulesId(e.getId());
+        })).collect(Collectors.toList());
+        qwSopTempContentService.saveList(contentList);
+    }
+
     @Override
     @DataSource(DataSourceType.SOP)
     public int update(QwSopTemp qwSopTemp) {

+ 21 - 14
fs-service-system/src/main/java/com/fs/statis/StatisticsRedisConstant.java

@@ -7,58 +7,65 @@ public class StatisticsRedisConstant {
     /**
      * 经销商统计
      */
-    public static final String DATA_OVERVIEW_DEALER_AGGREGATED = "statistics::data::overview::DealerAggregatedDTO";
+    public static final String DATA_OVERVIEW_DEALER_AGGREGATED = "overview::DealerAggregatedDTO";
     /**
      * 短信余额
      */
-    public static final String DATA_OVERVIEW_DEALER_SMS_BALANCE = "statistics::data::overview::SMS::BALANCE";
+    public static final String DATA_OVERVIEW_DEALER_SMS_BALANCE = "overview::SMS::BALANCE";
     /**
      * 余额类
      */
-    public static final String DATA_OVERVIEW_DEALER_BALANCE = "statistics::data::overview::balance";
+    public static final String DATA_OVERVIEW_DEALER_BALANCE = "overview::balance";
     /**
      * 平台统计类信息
      */
-    public static final String DATA_OVERVIEW_DEALER_AUTHORIZATION_INFO = "statistics::data::overview::authorizationInfo";
+    public static final String DATA_OVERVIEW_DEALER_AUTHORIZATION_INFO = "overview::authorizationInfo";
 
     /**
      * 分析概览-今日
      */
-    public static final String DATA_OVERVIEW_DEALER_ANALYSISPREVIEW_TODAY = "statistics::data::overview::AnalysisPreviewDTO::0";
+    public static final String DATA_OVERVIEW_DEALER_ANALYSISPREVIEW_TODAY = "overview::AnalysisPreviewDTO::0";
     /**
      * 分析概览-昨日
      */
-    public static final String DATA_OVERVIEW_DEALER_ANALYSISPREVIEW_YESTODAY = "statistics::data::overview::AnalysisPreviewDTO::1";
+    public static final String DATA_OVERVIEW_DEALER_ANALYSISPREVIEW_YESTODAY = "overview::AnalysisPreviewDTO::1";
 
     /**
      * 分析概览-本周
      */
-    public static final String DATA_OVERVIEW_DEALER_ANALYSISPREVIEW_THIS_WEEEK = "statistics::data::overview::AnalysisPreviewDTO::2";
+    public static final String DATA_OVERVIEW_DEALER_ANALYSISPREVIEW_THIS_WEEEK = "overview::AnalysisPreviewDTO::2";
 
     /**
      * 分析概览-本月
      */
-    public static final String DATA_OVERVIEW_DEALER_ANALYSISPREVIEW_THIS_MONTH = "statistics::data::overview::AnalysisPreviewDTO::3";
+    public static final String DATA_OVERVIEW_DEALER_ANALYSISPREVIEW_THIS_MONTH = "overview::AnalysisPreviewDTO::3";
     /**
      * 分析概览-上月
      */
-    public static final String DATA_OVERVIEW_DEALER_ANALYSISPREVIEW_BEFORE_MONTH = "statistics::data::overview::AnalysisPreviewDTO::4";
+    public static final String DATA_OVERVIEW_DEALER_ANALYSISPREVIEW_BEFORE_MONTH = "overview::AnalysisPreviewDTO::4";
 
 
     /**
      * 会员观看、完播人数趋势图
      */
-    public static final String DATA_OVERVIEW_DEALER_CHARTS = "statistics::data::charts::dealer::charts";
+    public static final String DATA_OVERVIEW_DEALER_CHARTS = "charts::dealer::charts";
 
 
     /**
      * 经销商会员观看TOP10 - 按观看人数
      */
-    public static final String CHARTS_MEMBER_TOP_TEN_WATCH = "statistics::data::charts::memeber::top10::watch::user::count";
+    public static final String CHARTS_MEMBER_TOP_TEN_WATCH = "charts::memeber::top10::watch::user::count";
     /**
-     * 经销商会员观看TOP10 - 按完播人数
+     * 课程观看TOP10
      */
-    public static final String CHARTS_MEMBER_TOP_TEN_COMPLETED = "statistics::data:charts::memeber::top10::watch::completed::user::count";
-
+    public static final String CHARTS_WATCH_TOP_TEN = "charts::watch::top10";
+    /**
+     * 答题红包金额TOP10
+     */
+    public static final String CHARTS_REWARD_MONEY_TOP_TEN = "charts::reward::money::top10";
+    /**
+     * 答题红包金额趋势图
+     */
+    public static final String CHARTS_REWARD_MONEY_TREND = "charts::reward::money::trend";
 
 }

+ 9 - 2
fs-service-system/src/main/java/com/fs/statis/service/IStatisticsService.java

@@ -25,15 +25,22 @@ public interface IStatisticsService {
      */
     void watchEndPlayTrendTask(Integer type);
 
+
+    /**
+     * 经销商会员观看TOP10
+     */
+    void companyWatchCourseTopTenTask(Integer type,Integer statisticalType);
+
     /**
      * 课程观看TOP10
      */
-    void watchCourseTopTenTask();
+    void watchCourseTopTenTask(Integer type,Integer statisticalType,String sort);
 
     /**
      * 答题红包金额TOP10
      */
-    void rewardMoneyTopTenTask();
+    void rewardMoneyTopTenTask(Integer type,Integer dataType);
+    void rewardMoneyTradeTask(Integer type);
 
     /**
      * 分析概览 - 经销商统计

+ 277 - 4
fs-service-system/src/main/java/com/fs/statis/service/impl/StatisticsServiceImpl.java

@@ -24,9 +24,9 @@ import java.time.format.DateTimeFormatter;
 import java.time.temporal.TemporalAdjusters;
 import java.util.List;
 
-import static com.fs.statis.StatisticsRedisConstant.DATA_OVERVIEW_DEALER_CHARTS;
+import static com.fs.statis.StatisticsRedisConstant.*;
 
-@Service
+@Service("statisticsService")
 public class StatisticsServiceImpl implements IStatisticsService {
     @Autowired
     private ConsumptionBalanceMapper consumptionBalanceMapper;
@@ -185,13 +185,286 @@ public class StatisticsServiceImpl implements IStatisticsService {
 
     }
 
+
+    @Scheduled(cron = "0 0/15 * * * *")
+    public void companyWatchCourseTopTenTask0(){
+        companyWatchCourseTopTenTask(0,0);
+        companyWatchCourseTopTenTask(0,1);
+    }
+
+    @Scheduled(cron = "0 0 1 * * *")
+    public void companyWatchCourseTopTenTask1(){
+        companyWatchCourseTopTenTask(1,0);
+        companyWatchCourseTopTenTask(1,1);
+
+        companyWatchCourseTopTenTask(2,0);
+        companyWatchCourseTopTenTask(2,1);
+
+
+        companyWatchCourseTopTenTask(3,0);
+        companyWatchCourseTopTenTask(3,1);
+
+        companyWatchCourseTopTenTask(4,0);
+        companyWatchCourseTopTenTask(4,1);
+    }
+
+    @Override
+    public void companyWatchCourseTopTenTask(Integer type,Integer statisticalType) {
+
+        AnalysisPreviewQueryDTO dto = new AnalysisPreviewQueryDTO();
+        dto.setType(type);
+        dto.setStatisticalType(statisticalType);
+
+        String startDate = "";
+        String endDate = "";
+
+        LocalDateTime now = LocalDateTime.now();
+        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
+
+
+        if(0 == type){
+            startDate = now.format(formatter);
+            endDate = now.format(formatter);
+        } else if(1 == type){
+            LocalDateTime yesterday = now.minusDays(1);
+            startDate = yesterday.format(formatter);
+            endDate = yesterday.format(formatter);
+        } else if(2 == type) {
+            LocalDateTime startOfWeek = now.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY));
+            startDate = startOfWeek.format(formatter);
+            endDate = now.format(formatter);
+        } else if(3 == type) {
+            LocalDateTime startOfMonth = now.withDayOfMonth(1);
+            startDate = startOfMonth.format(formatter);
+            endDate = now.format(formatter);
+        } else if(4 == type) {
+            LocalDateTime firstDayOfPreviousMonth = now.minusMonths(1).withDayOfMonth(1);
+            LocalDateTime lastDayOfPreviousMonth = now.withDayOfMonth(1).minusDays(1);
+            startDate = firstDayOfPreviousMonth.format(formatter);
+            endDate = lastDayOfPreviousMonth.format(formatter);
+        }
+
+        dto.setStartTime(startDate);
+        dto.setEndTime(endDate);
+
+        List<DeaMemberTopTenDTO> deaMemberTopTenDTOS = deaMemberTopTen(dto);
+        redisCache.setCacheObject(String.format("%s::%d::%d", CHARTS_MEMBER_TOP_TEN_WATCH, type,statisticalType), deaMemberTopTenDTOS);
+    }
+
+    @Override
+    public void watchCourseTopTenTask(Integer type,Integer statisticalType,String sort) {
+        AnalysisPreviewQueryDTO dto = new AnalysisPreviewQueryDTO();
+        dto.setType(type);
+        dto.setStatisticalType(statisticalType);
+        dto.setSort(sort);
+
+        String startDate = "";
+        String endDate = "";
+
+        LocalDateTime now = LocalDateTime.now();
+        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
+
+
+        if(0 == type){
+            startDate = now.format(formatter);
+            endDate = now.format(formatter);
+        } else if(1 == type){
+            LocalDateTime yesterday = now.minusDays(1);
+            startDate = yesterday.format(formatter);
+            endDate = yesterday.format(formatter);
+        } else if(2 == type) {
+            LocalDateTime startOfWeek = now.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY));
+            startDate = startOfWeek.format(formatter);
+            endDate = now.format(formatter);
+        } else if(3 == type) {
+            LocalDateTime startOfMonth = now.withDayOfMonth(1);
+            startDate = startOfMonth.format(formatter);
+            endDate = now.format(formatter);
+        } else if(4 == type) {
+            LocalDateTime firstDayOfPreviousMonth = now.minusMonths(1).withDayOfMonth(1);
+            LocalDateTime lastDayOfPreviousMonth = now.withDayOfMonth(1).minusDays(1);
+            startDate = firstDayOfPreviousMonth.format(formatter);
+            endDate = lastDayOfPreviousMonth.format(formatter);
+        }
+
+        dto.setStartTime(startDate);
+        dto.setEndTime(endDate);
+
+        List<CourseStatsDTO> courseStatsDTOS = watchCourseTopTen(dto);
+
+        redisCache.setCacheObject( String.format("%s::%d::%d::%s", CHARTS_WATCH_TOP_TEN, type,statisticalType,sort), courseStatsDTOS);
+    }
+
+    @Scheduled(cron = "0 0/15 * * * *")
+    public void watchCourseTopTenTask0(){
+        watchCourseTopTenTask(0,0,"DESC");
+        watchCourseTopTenTask(0,0,"ASC");
+
+        watchCourseTopTenTask(0,1,"DESC");
+        watchCourseTopTenTask(0,1,"ASC");
+
+        watchCourseTopTenTask(0,2,"DESC");
+        watchCourseTopTenTask(0,2,"ASC");
+
+        watchCourseTopTenTask(0,3,"DESC");
+        watchCourseTopTenTask(0,3,"ASC");
+    }
+
+    @Scheduled(cron = "0 0 1 * * *")
+    public void watchCourseTopTenTask1(){
+        watchCourseTopTenTask(1,0,"DESC");
+        watchCourseTopTenTask(1,0,"ASC");
+
+        watchCourseTopTenTask(1,1,"DESC");
+        watchCourseTopTenTask(1,1,"ASC");
+
+        watchCourseTopTenTask(1,2,"DESC");
+        watchCourseTopTenTask(1,2,"ASC");
+
+        watchCourseTopTenTask(1,3,"DESC");
+        watchCourseTopTenTask(1,3,"ASC");
+
+
+        watchCourseTopTenTask(2,0,"DESC");
+        watchCourseTopTenTask(2,0,"ASC");
+
+        watchCourseTopTenTask(2,1,"DESC");
+        watchCourseTopTenTask(2,1,"ASC");
+
+        watchCourseTopTenTask(2,2,"DESC");
+        watchCourseTopTenTask(2,2,"ASC");
+
+        watchCourseTopTenTask(2,3,"DESC");
+        watchCourseTopTenTask(2,3,"ASC");
+
+
+        watchCourseTopTenTask(3,0,"DESC");
+        watchCourseTopTenTask(3,0,"ASC");
+
+        watchCourseTopTenTask(3,1,"DESC");
+        watchCourseTopTenTask(3,1,"ASC");
+
+        watchCourseTopTenTask(3,2,"DESC");
+        watchCourseTopTenTask(3,2,"ASC");
+
+        watchCourseTopTenTask(3,3,"DESC");
+        watchCourseTopTenTask(3,3,"ASC");
+    }
+
+
+    @Scheduled(cron = "0 0/15 * * * *")
+    public void rewardMoneyTask15Minutes(){
+        rewardMoneyTopTenTask(0,0);
+        rewardMoneyTopTenTask(0,1);
+
+        rewardMoneyTradeTask(0);
+    }
+
+
+    @Scheduled(cron = "0 0 1 * * *")
+    public void rewardMoneyTaskEveryday(){
+        rewardMoneyTopTenTask(1,0);
+        rewardMoneyTopTenTask(1,1);
+
+
+        rewardMoneyTopTenTask(2,0);
+        rewardMoneyTopTenTask(2,1);
+
+        rewardMoneyTopTenTask(3,0);
+        rewardMoneyTopTenTask(3,1);
+
+        rewardMoneyTopTenTask(4,0);
+        rewardMoneyTopTenTask(4,1);
+
+
+        rewardMoneyTradeTask(1);
+        rewardMoneyTradeTask(2);
+        rewardMoneyTradeTask(3);
+        rewardMoneyTradeTask(4);
+    }
+
     @Override
-    public void watchCourseTopTenTask() {
+    public void rewardMoneyTopTenTask(Integer type,Integer dataType) {
+        AnalysisPreviewQueryDTO dto = new AnalysisPreviewQueryDTO();
+        dto.setType(type);
+        dto.setDataType(dataType);
+
+        String startDate = "";
+        String endDate = "";
+
+        LocalDateTime now = LocalDateTime.now();
+        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
+
+
+        if(0 == type){
+            startDate = now.format(formatter);
+            endDate = now.format(formatter);
+        } else if(1 == type){
+            LocalDateTime yesterday = now.minusDays(1);
+            startDate = yesterday.format(formatter);
+            endDate = yesterday.format(formatter);
+        } else if(2 == type) {
+            LocalDateTime startOfWeek = now.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY));
+            startDate = startOfWeek.format(formatter);
+            endDate = now.format(formatter);
+        } else if(3 == type) {
+            LocalDateTime startOfMonth = now.withDayOfMonth(1);
+            startDate = startOfMonth.format(formatter);
+            endDate = now.format(formatter);
+        } else if(4 == type) {
+            LocalDateTime firstDayOfPreviousMonth = now.minusMonths(1).withDayOfMonth(1);
+            LocalDateTime lastDayOfPreviousMonth = now.withDayOfMonth(1).minusDays(1);
+            startDate = firstDayOfPreviousMonth.format(formatter);
+            endDate = lastDayOfPreviousMonth.format(formatter);
+        }
+
+        dto.setStartTime(startDate);
+        dto.setEndTime(endDate);
+
+        List<RewardMoneyTopTenDTO> rewardMoneyTopTenDTOS = rewardMoneyTopTen(dto);
+
+        redisCache.setCacheObject( String.format("%s::%d::%d", CHARTS_REWARD_MONEY_TOP_TEN, type,dataType), rewardMoneyTopTenDTOS);
 
     }
 
     @Override
-    public void rewardMoneyTopTenTask() {
+    public void rewardMoneyTradeTask(Integer type) {
+        AnalysisPreviewQueryDTO dto = new AnalysisPreviewQueryDTO();
+        dto.setType(type);
+
+        String startDate = "";
+        String endDate = "";
+
+        LocalDateTime now = LocalDateTime.now();
+        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
+
+
+        if(0 == type){
+            startDate = now.format(formatter);
+            endDate = now.format(formatter);
+        } else if(1 == type){
+            LocalDateTime yesterday = now.minusDays(1);
+            startDate = yesterday.format(formatter);
+            endDate = yesterday.format(formatter);
+        } else if(2 == type) {
+            LocalDateTime startOfWeek = now.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY));
+            startDate = startOfWeek.format(formatter);
+            endDate = now.format(formatter);
+        } else if(3 == type) {
+            LocalDateTime startOfMonth = now.withDayOfMonth(1);
+            startDate = startOfMonth.format(formatter);
+            endDate = now.format(formatter);
+        } else if(4 == type) {
+            LocalDateTime firstDayOfPreviousMonth = now.minusMonths(1).withDayOfMonth(1);
+            LocalDateTime lastDayOfPreviousMonth = now.withDayOfMonth(1).minusDays(1);
+            startDate = firstDayOfPreviousMonth.format(formatter);
+            endDate = lastDayOfPreviousMonth.format(formatter);
+        }
+
+        dto.setStartTime(startDate);
+        dto.setEndTime(endDate);
+        List<RewardMoneyTrendDTO> rewardMoneyTrendDTOS = rewardMoneyTrendDTO(dto);
+        redisCache.setCacheObject( String.format("%s::%d", CHARTS_REWARD_MONEY_TREND, type), rewardMoneyTrendDTOS);
 
     }
 

+ 19 - 1
fs-service-system/src/main/resources/mapper/course/FsUserCourseVideoMapper.xml

@@ -32,10 +32,13 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         <result property="packageJson"    column="package_json"    />
         <result property="isTranscode"    column="is_transcode"    />
         <result property="transcodeFileKey"    column="transcode_file_key"    />
+        <result property="viewStartTime"    column="view_start_time"    />
+        <result property="viewEndTime"    column="view_end_time"    />
+        <result property="lastJoinTime"    column="last_join_time"    />
     </resultMap>
 
     <sql id="selectFsUserCourseVideoVo">
-        select video_id,line_one,package_json,is_transcode,transcode_file_key,file_size,file_key,round,red_packet_money,line_two,upload_type,line_three, file_id,file_name,is_del, title, description, video_url, thumbnail, duration, update_time, create_time, talent_id, course_id, status, course_sort, question_bank_id from fs_user_course_video
+        select * from fs_user_course_video
     </sql>
 
     <select id="selectFsUserCourseVideoList" parameterType="FsUserCourseVideo" resultMap="FsUserCourseVideoResult">
@@ -89,6 +92,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="packageJson != null">package_json,</if>
             <if test="isTranscode != null">is_transcode,</if>
             <if test="transcodeFileKey != null">transcode_file_key,</if>
+            <if test="viewStartTime != null">view_start_time,</if>
+            <if test="viewEndTime != null">view_end_time,</if>
+            <if test="lastJoinTime != null">last_join_time,</if>
          </trim>
         <trim prefix="values (" suffix=")" suffixOverrides=",">
             <if test="fileId != null">#{fileId},</if>
@@ -117,6 +123,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="packageJson != null">#{packageJson},</if>
             <if test="isTranscode != null">#{isTranscode},</if>
             <if test="transcodeFileKey != null">#{transcodeFileKey},</if>
+            <if test="viewStartTime != null">#{viewStartTime},</if>
+            <if test="viewEndTime != null">#{viewEndTime},</if>
+            <if test="lastJoinTime != null">#{lastJoinTime},</if>
          </trim>
     </insert>
 
@@ -149,6 +158,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="packageJson != null">package_json = #{packageJson},</if>
             <if test="isTranscode != null">is_transcode = #{isTranscode},</if>
             <if test="transcodeFileKey != null">transcode_file_key = #{transcodeFileKey},</if>
+            <if test="viewStartTime != null">view_start_time = #{viewStartTime},</if>
+            <if test="viewEndTime != null">view_end_time = #{viewEndTime},</if>
+            <if test="lastJoinTime != null">last_join_time = #{lastJoinTime},</if>
         </trim>
         where video_id = #{videoId}
     </update>
@@ -163,6 +175,12 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             #{videoId}
         </foreach>
     </update>
+    <update id="updates">
+        update fs_user_course_video set view_start_time = #{viewStartTime},view_end_time = #{viewEndTime},last_join_time = #{lastJoinTime} where video_id in
+        <foreach item="videoId" collection="ids" open="(" separator="," close=")">
+            #{videoId}
+        </foreach>
+    </update>
 
     <select id="selectFsUserCourseVideoPageList" resultType="FsUserCourseVideoPageListVO">
         SELECT

+ 5 - 0
fs-service-system/src/main/resources/mapper/sop/QwSopTempMapper.xml

@@ -74,6 +74,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="data.gap != null">gap,</if>
             <if test="data.sendType != null">send_type,</if>
             <if test="data.updateTime != null">update_time,</if>
+            <if test="data.project != null">project,</if>
+            <if test="data.courseId != null">course_id,</if>
          </trim>
         <trim prefix="values (" suffix=")" suffixOverrides=",">
             <if test="data.id != null">#{data.id},</if>
@@ -87,6 +89,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="data.gap != null">#{data.gap},</if>
             <if test="data.sendType != null">#{data.sendType},</if>
             <if test="data.updateTime != null">#{data.updateTime},</if>
+            <if test="data.project != null">#{data.project},</if>
+            <if test="data.courseId != null">#{data.courseId},</if>
          </trim>
     </insert>
 
@@ -104,6 +108,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="data.sendType != null">send_type = #{data.sendType},</if>
             <if test="data.updateTime != null">update_time = #{data.updateTime},</if>
             <if test="data.project != null">project = #{data.project},</if>
+            <if test="data.courseId != null">course_id = #{data.courseId},</if>
         </trim>
         where id = #{data.id}
     </update>