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

Merge remote-tracking branch 'origin/master'

ct 1 тиждень тому
батько
коміт
a4b5c3b56d
20 змінених файлів з 554 додано та 79 видалено
  1. 17 0
      fs-admin/src/main/java/com/fs/course/controller/FsUserCourseController.java
  2. 19 0
      fs-admin/src/main/java/com/fs/course/controller/FsUserCourseVideoController.java
  3. 42 33
      fs-admin/src/main/java/com/fs/his/controller/FsUserController.java
  4. 6 2
      fs-qw-task/src/main/java/com/fs/app/controller/CommonController.java
  5. 1 1
      fs-qw-task/src/main/java/com/fs/app/task/qwTask.java
  6. 2 1
      fs-qw-task/src/main/java/com/fs/app/taskService/SopLogsTaskService.java
  7. 29 10
      fs-qw-task/src/main/java/com/fs/app/taskService/impl/SopLogsTaskServiceImpl.java
  8. 8 0
      fs-service/src/main/java/com/fs/course/mapper/FsUserCourseVideoMapper.java
  9. 6 0
      fs-service/src/main/java/com/fs/course/service/IFsUserCourseVideoService.java
  10. 30 0
      fs-service/src/main/java/com/fs/course/service/impl/FsUserCourseVideoServiceImpl.java
  11. 58 0
      fs-service/src/main/java/com/fs/his/dto/FsUserDTO.java
  12. 26 26
      fs-service/src/main/java/com/fs/his/mapper/FsUserMapper.java
  13. 15 4
      fs-service/src/main/java/com/fs/his/service/impl/FsUserServiceImpl.java
  14. 15 0
      fs-service/src/main/java/com/fs/qw/param/FsUserCourseRedPageParam.java
  15. 1 1
      fs-service/src/main/java/com/fs/sop/mapper/SopUserLogsMapper.java
  16. 1 1
      fs-service/src/main/java/com/fs/sop/service/impl/SopUserLogsServiceImpl.java
  17. 104 0
      fs-service/src/main/resources/application-config-dev-czt.yml
  18. 157 0
      fs-service/src/main/resources/application-dev-czt.yml
  19. 13 0
      fs-service/src/main/resources/mapper/course/FsUserCourseVideoMapper.xml
  20. 4 0
      fs-service/src/main/resources/mapper/sop/SopUserLogsMapper.xml

+ 17 - 0
fs-admin/src/main/java/com/fs/course/controller/FsUserCourseController.java

@@ -8,10 +8,12 @@ import com.fs.common.core.domain.R;
 import com.fs.common.core.domain.model.LoginUser;
 import com.fs.common.utils.ServletUtils;
 import com.fs.course.config.CourseConfig;
+import com.fs.course.service.IFsUserCourseVideoService;
 import com.fs.course.vo.FsUserCourseListPVO;
 import com.fs.framework.web.service.TokenService;
 import com.fs.his.utils.RedisCacheUtil;
 import com.fs.his.vo.OptionsVO;
+import com.fs.qw.param.FsUserCourseRedPageParam;
 import com.fs.system.service.ISysConfigService;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -45,6 +47,9 @@ public class FsUserCourseController extends BaseController
     @Autowired
     private IFsUserCourseService fsUserCourseService;
 
+    @Autowired
+    private IFsUserCourseVideoService courseVideoService;
+
     @Autowired
     private RedisCacheUtil redisCacheUtil;
 
@@ -207,6 +212,18 @@ public class FsUserCourseController extends BaseController
         return toAjax(1);
     }
 
+    /**
+     * 统一修改课程红包
+     */
+    @PreAuthorize("@ss.hasPermi('course:userCourse:editRedPage')")
+    @Log(title = "修改课程红包", businessType = BusinessType.UPDATE)
+    @PostMapping("/editRedPage")
+    public AjaxResult editRedPage(@RequestBody FsUserCourseRedPageParam redPageParam)
+    {
+        courseVideoService.updateFsUserCourseRedPage(redPageParam);
+        return toAjax(1);
+    }
+
     /**
      * 修改课程
      */

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

@@ -23,6 +23,7 @@ import com.fs.course.service.IFsUserCourseVideoService;
 import com.fs.course.vo.FsUserCourseVideoChooseVO;
 import com.fs.framework.web.service.TokenService;
 import com.fs.his.vo.OptionsVO;
+import com.fs.qw.vo.SortDayVo;
 import com.fs.system.service.ISysConfigService;
 import com.github.pagehelper.PageHelper;
 import com.github.pagehelper.PageInfo;
@@ -176,6 +177,24 @@ public class FsUserCourseVideoController extends BaseController
         return getDataTable(list);
     }
 
+    @GetMapping("/getVideoListByCourseIdAll")
+    public TableDataInfo getVideoListByCourseIdAll(Long courseId)
+    {
+
+        FsUserCourseVideo courseVideo=new FsUserCourseVideo();
+        courseVideo.setCourseId(courseId);
+        courseVideo.setIsDel(0);
+        List<FsUserCourseVideo> list = fsUserCourseVideoService.selectFsUserCourseVideoList(courseVideo);
+        return getDataTable(list);
+    }
+
+    @PostMapping("/sortCourseVideo")
+    public AjaxResult sortCourseVideo(@RequestBody List<FsUserCourseVideo> list){
+        fsUserCourseVideoService.sortCourseVideo(list);
+        return toAjax(1);
+    }
+
+
     @GetMapping("/getSort/{courseId}")
     public R remove(@PathVariable("courseId") Long courseId)
     {

+ 42 - 33
fs-admin/src/main/java/com/fs/his/controller/FsUserController.java

@@ -18,6 +18,7 @@ import com.fs.course.param.FsCourseLinkCreateParam;
 import com.fs.course.service.IFsUserCompanyUserService;
 import com.fs.course.service.IFsUserCourseService;
 import com.fs.his.domain.FsUserAddress;
+import com.fs.his.dto.FsUserDTO;
 import com.fs.his.enums.FsUserIntegralLogTypeEnum;
 import com.fs.his.mapper.FsUserMapper;
 import com.fs.his.param.FsUserAddIntegralTemplateParam;
@@ -121,6 +122,47 @@ public class FsUserController extends BaseController
         return getDataTable(list);
     }
 
+    /**
+     * 导出用户列表
+     */
+    @PreAuthorize("@ss.hasPermi('his:user:export')")
+    @Log(title = "用户", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(FsUserParam fsUser)
+    {
+        logger.info("导出用户列表:"+ SecurityUtils.getUserId());
+        if (fsUserService.isEntityNull(fsUser)){
+            return AjaxResult.error("请筛选数据导出");
+        }
+        Long count = fsUserService.selectFsUserExportListVOCount(fsUser);
+        if (count>10000){
+            return AjaxResult.error("导出数据不可超过1w条");
+        }
+        List<FsUserVO> list = fsUserService.selectFsUserListVO(fsUser);
+        SysRole sysRole = isCheckPermission();
+        List<FsUserDTO> listDTO = Lists.newArrayList();
+        for (FsUserVO fsUserVO : list) {
+            if(fsUserVO.getPhone() != null&&fsUserVO.getPhone()!=""){
+                if (!(sysRole.getIsCheckPhone()==1)){
+                    if (fsUserVO.getPhone().length()>11){
+                        fsUserVO.setPhone(decryptPhoneMk(fsUserVO.getPhone()));
+                    }else {
+                        fsUserVO.setPhone(fsUserVO.getPhone().replaceAll("(\\d{3})\\d*(\\d{4})", "$1****$2"));
+                    }
+                } else {
+                    if (fsUserVO.getPhone().length()>11) {
+                        fsUserVO.setPhone(decryptPhone(fsUserVO.getPhone()));
+                    }
+                }
+            }
+            FsUserDTO fsUserDTO = new FsUserDTO();
+            BeanUtils.copyProperties(fsUserVO,fsUserDTO);
+            listDTO.add(fsUserDTO);
+        }
+        ExcelUtil<FsUserDTO> util = new ExcelUtil<FsUserDTO>(FsUserDTO.class);
+        return util.exportExcel(listDTO, "用户数据");
+    }
+
     @Autowired
     private ISysRoleService sysRoleService;
     private SysRole isCheckPermission() {
@@ -196,37 +238,6 @@ public class FsUserController extends BaseController
         return util.exportExcel(list, "项目会员数据");
     }
 
-    /**
-     * 导出用户列表
-     */
-    @PreAuthorize("@ss.hasPermi('his:user:export')")
-    @Log(title = "用户", businessType = BusinessType.EXPORT)
-    @GetMapping("/export")
-    public AjaxResult export(FsUserParam fsUser)
-    {
-        logger.info("导出用户列表:"+ SecurityUtils.getUserId());
-        if (fsUserService.isEntityNull(fsUser)){
-            return AjaxResult.error("请筛选数据导出");
-        }
-        Long count = fsUserService.selectFsUserExportListVOCount(fsUser);
-        if (count>10000){
-            return AjaxResult.error("导出数据不可超过1w条");
-        }
-        List<FsUserExportListVO> list = fsUserService.selectFsUserExportListVO(fsUser);
-        SysRole sysRole = isCheckPermission();
-        for (FsUserExportListVO vo : list) {
-            if (vo.getMobile()!=null && !(sysRole.getIsCheckPhone()==1)){
-                vo.setMobile(vo.getMobile().replaceAll("(\\d{3})\\d*(\\d{4})", "$1****$2"));
-            } else {
-                if (vo.getMobile().length()>11){
-                    vo.setMobile(decryptPhone(vo.getMobile()));
-                }
-            }
-        }
-        ExcelUtil<FsUserExportListVO> util = new ExcelUtil<FsUserExportListVO>(FsUserExportListVO.class);
-        return util.exportExcel(list, "用户数据");
-    }
-
     /**
      * 获取用户详细信息
      */
@@ -238,8 +249,6 @@ public class FsUserController extends BaseController
         return AjaxResult.success(fsUser);
     }
 
-
-
     @GetMapping(value = "/getUserAddr/{userId}")
     public AjaxResult getUserAddr(@PathVariable("userId") Long userId)
     {

+ 6 - 2
fs-qw-task/src/main/java/com/fs/app/controller/CommonController.java

@@ -259,7 +259,7 @@ public class CommonController {
     }
 
     @GetMapping("/test")
-    public R test(String time) throws Exception {
+    public R test(String time, String sopId) throws Exception {
         log.info("进入sop任务");
 //        LocalDateTime currentTime = DateUtil.parseLocalDateTime(time);
 //        // 计算下一个整点时间
@@ -268,7 +268,11 @@ public class CommonController {
 //        // 打印日志,确认时间
 //        log.info("任务实际执行时间: {}", currentTime);
 //        log.info("传递给任务的时间参数: {}", nextHourTime);
-        sopLogsTaskService.selectSopUserLogsListByTime(DateUtil.parseLocalDateTime(time));
+        List<String> sopidList = new ArrayList<>();
+        if(StringUtils.isNotEmpty(sopId)){
+            sopidList = Arrays.asList(sopId.split(","));
+        }
+        sopLogsTaskService.selectSopUserLogsListByTime(DateUtil.parseLocalDateTime(time), sopidList);
         return R.ok();
     }
     @GetMapping("/testWx")

+ 1 - 1
fs-qw-task/src/main/java/com/fs/app/task/qwTask.java

@@ -117,7 +117,7 @@ public class qwTask {
         log.info("任务实际执行时间: {}", currentTime);
 
         // 调用服务方法处理SOP用户日志
-        sopLogsTaskService.selectSopUserLogsListByTime(currentTime);
+        sopLogsTaskService.selectSopUserLogsListByTime(currentTime, null);
     }
 
     /**

+ 2 - 1
fs-qw-task/src/main/java/com/fs/app/taskService/SopLogsTaskService.java

@@ -1,10 +1,11 @@
 package com.fs.app.taskService;
 
 import java.time.LocalDateTime;
+import java.util.List;
 
 public interface SopLogsTaskService {
 
-    public void selectSopUserLogsListByTime(LocalDateTime currentTime) throws Exception;
+    public void selectSopUserLogsListByTime(LocalDateTime currentTime, List<String> sopidList) throws Exception;
 
 
     /**

+ 29 - 10
fs-qw-task/src/main/java/com/fs/app/taskService/impl/SopLogsTaskServiceImpl.java

@@ -5,8 +5,6 @@ import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONArray;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.fs.app.taskService.SopLogsTaskService;
-import com.fs.common.core.domain.R;
-import com.fs.common.exception.base.BaseException;
 import com.fs.common.utils.PubFun;
 import com.fs.common.utils.StringUtils;
 import com.fs.company.domain.Company;
@@ -19,7 +17,6 @@ import com.fs.config.cloud.CloudHostProper;
 import com.fs.course.config.CourseConfig;
 import com.fs.course.domain.*;
 import com.fs.course.mapper.*;
-import com.fs.course.param.FsCourseLinkCreateParam;
 import com.fs.course.service.IFsCourseLinkService;
 import com.fs.course.service.IFsUserCompanyBindService;
 import com.fs.qw.domain.*;
@@ -286,7 +283,7 @@ public class SopLogsTaskServiceImpl implements SopLogsTaskService {
     }
 
     @Override
-    public void selectSopUserLogsListByTime(LocalDateTime currentTime) throws Exception {
+    public void selectSopUserLogsListByTime(LocalDateTime currentTime, List<String> sopidList) throws Exception {
         long startTimeMillis = System.currentTimeMillis();
         log.info("====== 开始选择和处理 SOP 用户日志 ======");
 
@@ -296,7 +293,7 @@ public class SopLogsTaskServiceImpl implements SopLogsTaskService {
             config = cachedCourseConfig;
         }
 
-        List<SopUserLogsVo> sopUserLogsVos = sopUserLogsMapper.selectSopUserLogsListByTime();
+        List<SopUserLogsVo> sopUserLogsVos = sopUserLogsMapper.selectSopUserLogsListByTime(sopidList);
         if (sopUserLogsVos.isEmpty()) {
             log.info("没有需要处理的 SOP 用户日志。");
             return;
@@ -1002,8 +999,22 @@ public class SopLogsTaskServiceImpl implements SopLogsTaskService {
                     break;
                 //小程序单独
                 case "4":
-
-                    addWatchLogIfNeeded(sopLogs, videoId, courseId, sendTime, qwUserId, companyUserId, companyId, externalId,logVo);
+                    if (isGroupChat) {
+                        try {
+                            groupChat.getChatUserList().stream().filter(e -> e.getUserList() != null && !e.getUserList().isEmpty()).forEach(e -> {
+                                Map<String, GroupUserExternalVo> userMap = PubFun.listToMapByGroupObject(e.getUserList(), GroupUserExternalVo::getUserId);
+                                GroupUserExternalVo vo = userMap.get(groupChat.getOwner());
+                                if (vo != null && vo.getId() != null) {
+                                    sopLogs.setFsUserId(vo.getFsUserId());
+                                    addWatchLogIfNeeded(sopLogs, videoId, courseId, sendTime, qwUserId, companyUserId, companyId, vo.getId().toString(), logVo);
+                                }
+                            });
+                        } catch (Exception e) {
+                            log.error("群聊创建看课记录失败!", e);
+                        }
+                    } else {
+                        addWatchLogIfNeeded(sopLogs, videoId, courseId, sendTime, qwUserId, companyUserId, companyId, externalId,logVo);
+                    }
 
                     String sortLink = createLinkByMiniApp(setting, logVo, sendTime, courseId, videoId,
                             qwUserId, companyUserId, companyId, externalId,isOfficial,sopLogs.getFsUserId(), isGroupChat ? groupChat.getChatId() : null);
@@ -1075,6 +1086,12 @@ public class SopLogsTaskServiceImpl implements SopLogsTaskService {
             }
 
         }
+        clonedContent.getSetting().stream().filter(e -> "1".equals(e.getIsBindUrl())).forEach(e -> {
+            e.setIsBindUrl("0");
+            e.setLinkDescribe(null);
+            e.setLinkUrl(null);
+            e.setLinkImageUrl(null);
+        });
         sopLogs.setContentJson(JSON.toJSONString(clonedContent));
         enqueueQwSopLogs(sopLogs);
     }
@@ -1364,10 +1381,12 @@ public class SopLogsTaskServiceImpl implements SopLogsTaskService {
         link.setCompanyId(Long.parseLong(companyId));
         link.setQwUserId(Long.parseLong(qwUserId));
         link.setCompanyUserId(Long.parseLong(companyUserId));
-        link.setVideoId(videoId.longValue());
+        link.setVideoId(videoId);
         link.setCorpId(logVo.getCorpId());
-        link.setCourseId(courseId.longValue());
-        link.setQwExternalId(Long.parseLong(externalId));
+        link.setCourseId(courseId);
+        if(StringUtils.isEmpty(chatId)){
+            link.setQwExternalId(Long.parseLong(externalId));
+        }
         link.setProjectCode(cloudHostProper.getProjectCode());
         link.setChatId(chatId);
 

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

@@ -9,6 +9,7 @@ import com.fs.course.param.newfs.UserCourseVideoPageParam;
 import com.fs.course.vo.*;
 import com.fs.course.vo.newfs.FsUserCourseVideoPageListVO;
 import com.fs.his.vo.OptionsVO;
+import com.fs.qw.param.FsUserCourseRedPageParam;
 import org.apache.ibatis.annotations.Param;
 import org.apache.ibatis.annotations.Select;
 import org.apache.ibatis.annotations.Update;
@@ -59,6 +60,13 @@ public interface FsUserCourseVideoMapper
      */
     public int updateFsUserCourseVideo(FsUserCourseVideo fsUserCourseVideo);
 
+    @Update("<script> " +
+            "update fs_user_course_video set red_packet_money=#{data.redPacketMoney} where course_id=#{data.courseId} " +
+            "</script>")
+    public int updateFsUserCourseRedPage(@Param("data") FsUserCourseRedPageParam courseRedPageParam);
+
+    int batchUpdateByVideoId(@Param("list") List<Map<String, Object>> list);
+
     /**
      * 删除课堂视频
      *

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

@@ -1,5 +1,6 @@
 package com.fs.course.service;
 
+import com.baomidou.mybatisplus.extension.service.IService;
 import com.fs.common.core.domain.R;
 import com.fs.common.core.domain.ResponseResult;
 import com.fs.course.domain.FsUserCourseVideo;
@@ -15,6 +16,8 @@ import com.fs.course.vo.newfs.FsUserCourseVideoPageListVO;
 import com.fs.course.vo.newfs.FsUserVideoListVO;
 import com.fs.his.domain.FsUser;
 import com.fs.his.vo.OptionsVO;
+import com.fs.qw.param.FsUserCourseRedPageParam;
+import com.fs.sop.domain.QwSopTempDay;
 
 import java.util.List;
 import java.util.Map;
@@ -59,6 +62,9 @@ public interface IFsUserCourseVideoService
      */
     public int updateFsUserCourseVideo(FsUserCourseVideo fsUserCourseVideo);
 
+    public int updateFsUserCourseRedPage(FsUserCourseRedPageParam userCourseRedPageParam);
+    public void sortCourseVideo(List<FsUserCourseVideo> list);
+
     /**
      * 批量删除课堂视频
      *

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

@@ -15,8 +15,10 @@ import com.fs.common.core.domain.entity.SysDictData;
 import com.fs.common.core.redis.RedisCache;
 import com.fs.common.enums.BizResponseEnum;
 import com.fs.common.exception.CustomException;
+import com.fs.common.exception.base.BaseException;
 import com.fs.common.utils.CloudHostUtils;
 import com.fs.common.utils.DateUtils;
+import com.fs.common.utils.PubFun;
 import com.fs.common.utils.StringUtils;
 import com.fs.common.utils.date.DateUtil;
 import com.fs.company.constant.CompanyTrafficConstants;
@@ -55,12 +57,15 @@ import com.fs.qw.mapper.QwExternalContactMapper;
 import com.fs.qw.mapper.QwGroupChatMapper;
 import com.fs.qw.mapper.QwGroupChatUserMapper;
 import com.fs.qw.mapper.QwUserMapper;
+import com.fs.qw.param.FsUserCourseRedPageParam;
 import com.fs.qw.service.IQwCompanyService;
 import com.fs.qw.service.IQwExternalContactService;
+import com.fs.qw.vo.SortDayVo;
 import com.fs.qwApi.Result.QwAddContactWayResult;
 import com.fs.qwApi.Result.QwGroupChatDetailsResult;
 import com.fs.qwApi.param.QwAddContactWayParam;
 import com.fs.qwApi.service.QwApiService;
+import com.fs.sop.domain.QwSopTempDay;
 import com.fs.sop.domain.SopUserLogsInfo;
 import com.fs.sop.mapper.QwSopLogsMapper;
 import com.fs.sop.mapper.SopUserLogsInfoMapper;
@@ -309,6 +314,31 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
         return fsUserCourseVideoMapper.updateFsUserCourseVideo(fsUserCourseVideo);
     }
 
+    @Override
+    public int updateFsUserCourseRedPage(FsUserCourseRedPageParam userCourseRedPageParam) {
+
+        return fsUserCourseVideoMapper.updateFsUserCourseRedPage(userCourseRedPageParam);
+    }
+
+    @Override
+    public void sortCourseVideo(List<FsUserCourseVideo> list) {
+        if (list.isEmpty()){
+            return;
+        }
+        // 直接构建更新参数
+        List<Map<String, Object>> updateParams = list.stream()
+                .map(item -> {
+                    Map<String, Object> param = new HashMap<>();
+                    param.put("videoId", item.getVideoId());
+                    param.put("courseSort", item.getCourseSort());
+                    return param;
+                })
+                .collect(Collectors.toList());
+
+        // 批量更新
+        fsUserCourseVideoMapper.batchUpdateByVideoId(updateParams);
+    }
+
     /**
      * 批量删除课堂视频
      *

+ 58 - 0
fs-service/src/main/java/com/fs/his/dto/FsUserDTO.java

@@ -0,0 +1,58 @@
+package com.fs.his.dto;
+
+import com.fs.common.annotation.Excel;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+ * @description:
+ * @author: Guos
+ * @time: 2025/10/29 上午9:40
+ */
+@Data
+public class FsUserDTO {
+
+    @Excel(name = "用户ID")
+    private Long userId;
+
+    @Excel(name = "用户昵称")
+    private String nickName;
+
+    @Excel(name = "手机号码")
+    private String phone;
+
+    @Excel(name = "用户积分")
+    private Long integral;
+
+    @Excel(name = "用户状态:1为正常,0为禁止")
+    private Integer status;
+
+    @Excel(name = "用户备注")
+    private String remark;
+
+    @Excel(name = "上级昵称")
+    private String tuiName;
+
+    @Excel(name = "app来源")
+    private String source;
+
+    @Excel(name = "登陆设备")
+    private String loginDevice;
+
+    @Excel(name = "上级手机号码")
+    private String tuiPhone;
+
+    @Excel(name = "下级人数")
+    private Integer tuiUserCount;
+
+    @Excel(name = "最后一次登录ip")
+    private String lastIp;
+
+    @Excel(name = "余额")
+    private BigDecimal balance;
+
+    @Excel(name = "会员注册时间", dateFormat = "yyyy-MM-dd HH:mm:ss" , sort = 6)
+    private Date createTime;
+}

+ 26 - 26
fs-service/src/main/java/com/fs/his/mapper/FsUserMapper.java

@@ -105,6 +105,32 @@ public interface FsUserMapper
     })
     List<FsUserVO> selectFsUserListVO(FsUserParam fsUser);
 
+    @Select({"<script> " +
+            "SELECT  \n" +
+            "    fp.create_time ,\n" +
+            "    cu.nick_name ,\n" +
+            "    fu.user_id ,\n" +
+            "    fp.patient_name ,\n" +
+            "    fp.mobile ,\n" +
+            "    fu.is_buy \n" +
+            "FROM fs_user fu\n" +
+            "LEFT JOIN company_user_user cuu ON fu.user_id = cuu.user_id\n" +
+            "LEFT JOIN company_user cu ON cuu.company_user_id = cu.user_id\n" +
+            "LEFT JOIN fs_patient fp ON fu.user_id = fp.user_id\n" +
+            "WHERE fp.create_time IS NOT NULL and fu.is_del = 0 \n" +
+            "  <if test=\"companyUserId != null \"> and cuu.company_user_id=#{companyUserId} </if>\n" +
+            "  <if test=\"companyId != null \"> and cuu.company_id=#{companyId} </if>\n" +
+            "  <if test=\"nickName != null  and nickName != ''\"> and fu.nick_name like concat( #{nickName}, '%')</if>\n" +
+            "   <if test=\"phone != null  and phone != ''\"> and fu.phone like concat( #{phone}, '%')</if>\n" +
+            "   <if test=\"status != null \"> and fu.status = #{status}</if>\n" +
+            "            <if test=\"isBuy != null \"> and fu.is_buy = #{isBuy}</if>\n" +
+            "            <if test=\"userId != null \"> and fu.user_id = #{userId}</if>\n" +
+            "            <if test=\"sTime != null \">  and DATE(fu.create_time) &gt;= DATE(#{sTime})</if>\n" +
+            "            <if test=\"eTime != null \">  and DATE(fu.create_time) &lt;= DATE(#{eTime})</if>\n" +
+            "ORDER BY fu.user_id DESC "+
+            "</script>"})
+    List<FsUserExportListVO> selectFsUserExportListVO(FsUserParam fsUser);
+
     @Update("update fs_user set is_del=1 where user_id=#{userId}")
     int updateFsUserByUserId(Long userId);
 
@@ -144,32 +170,6 @@ public interface FsUserMapper
             "</script>"})
     List<FsUserVO> selectFsUserListVOByComponentsUser(FsUserParam fsUser);
 
-    @Select({"<script> " +
-            "SELECT  \n" +
-            "    fp.create_time ,\n" +
-            "    cu.nick_name ,\n" +
-            "    fu.user_id ,\n" +
-            "    fp.patient_name ,\n" +
-            "    fp.mobile ,\n" +
-            "    fu.is_buy \n" +
-            "FROM fs_user fu\n" +
-            "LEFT JOIN company_user_user cuu ON fu.user_id = cuu.user_id\n" +
-            "LEFT JOIN company_user cu ON cuu.company_user_id = cu.user_id\n" +
-            "LEFT JOIN fs_patient fp ON fu.user_id = fp.user_id\n" +
-            "WHERE fp.create_time IS NOT NULL and fu.is_del = 0 \n" +
-            "  <if test=\"companyUserId != null \"> and cuu.company_user_id=#{companyUserId} </if>\n" +
-            "  <if test=\"companyId != null \"> and cuu.company_id=#{companyId} </if>\n" +
-            "  <if test=\"nickName != null  and nickName != ''\"> and fu.nick_name like concat( #{nickName}, '%')</if>\n" +
-            "   <if test=\"phone != null  and phone != ''\"> and fu.phone like concat( #{phone}, '%')</if>\n" +
-            "   <if test=\"status != null \"> and fu.status = #{status}</if>\n" +
-            "            <if test=\"isBuy != null \"> and fu.is_buy = #{isBuy}</if>\n" +
-            "            <if test=\"userId != null \"> and fu.user_id = #{userId}</if>\n" +
-            "            <if test=\"sTime != null \">  and DATE(fu.create_time) &gt;= DATE(#{sTime})</if>\n" +
-            "            <if test=\"eTime != null \">  and DATE(fu.create_time) &lt;= DATE(#{eTime})</if>\n" +
-            "ORDER BY fu.user_id DESC "+
-            "</script>"})
-    List<FsUserExportListVO> selectFsUserExportListVO(FsUserParam fsUser);
-
     @Select("SELECT user_id\n" +
             "FROM fs_user_integral_logs\n" +
             "WHERE business_type = 2\n" +

+ 15 - 4
fs-service/src/main/java/com/fs/his/service/impl/FsUserServiceImpl.java

@@ -271,11 +271,26 @@ public class FsUserServiceImpl implements IFsUserService {
         return fsUserMapper.updateFsUserByUserId(userId);
     }
 
+    /**
+     * 列表查询
+     * @param fsUser
+     * @return
+     */
     @Override
     public List<FsUserVO> selectFsUserListVO(FsUserParam fsUser) {
         return fsUserMapper.selectFsUserListVO(fsUser);
     }
 
+    /**
+     * 导出用户列表
+     * @param fsUser
+     * @return
+     */
+    @Override
+    public List<FsUserExportListVO> selectFsUserExportListVO(FsUserParam fsUser) {
+        return fsUserMapper.selectFsUserExportListVO(fsUser);
+    }
+
     @Override
     public FsUser selectFsUserByOpenId(String openId) {
         return fsUserMapper.selectFsUserByOpenId(openId);
@@ -313,10 +328,6 @@ public class FsUserServiceImpl implements IFsUserService {
         return fsUserMapper.selectFsUserListVOByComponentsUser(fsUser);
     }
 
-    @Override
-    public List<FsUserExportListVO> selectFsUserExportListVO(FsUserParam fsUser) {
-        return fsUserMapper.selectFsUserExportListVO(fsUser);
-    }
     @Autowired
     private FsUserIntegralLogsMapper integralLogsMapper;
 

+ 15 - 0
fs-service/src/main/java/com/fs/qw/param/FsUserCourseRedPageParam.java

@@ -0,0 +1,15 @@
+package com.fs.qw.param;
+
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+@Data
+public class FsUserCourseRedPageParam {
+
+    //课程
+    private Long courseId;
+    //红包
+    private BigDecimal redPacketMoney;
+}
+

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

@@ -54,7 +54,7 @@ public interface SopUserLogsMapper {
 //    int updateSopUserLogsDistinctByList(@Param("data") SopUserLogsArray userLogsArray);
 
     @DataSource(DataSourceType.SOP)
-    public List<SopUserLogsVo> selectSopUserLogsListByTime();
+    public List<SopUserLogsVo> selectSopUserLogsListByTime(@Param("sopIds") List<String> sopidList);
 
     @DataSource(DataSourceType.SOP)
     public List<SopUserLogs> meetsTheRatingByUserInfo();

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

@@ -165,7 +165,7 @@ public class SopUserLogsServiceImpl  implements ISopUserLogsService {
         // 当前时间
         LocalDateTime currentDateTime = LocalDateTime.now();
 
-        List<SopUserLogsVo> sopUserLogsVos = sopUserLogsMapper.selectSopUserLogsListByTime();
+        List<SopUserLogsVo> sopUserLogsVos = sopUserLogsMapper.selectSopUserLogsListByTime(null);
         // 创建一个 Map,用于分组:key 是sop_id,value 是对应的 QwSopLogs 列表
         Map<String, List<SopUserLogsVo>> stringListMap = sopUserLogsVos.stream()
                 .collect(Collectors.groupingBy(SopUserLogsVo::getSopId));

+ 104 - 0
fs-service/src/main/resources/application-config-dev-czt.yml

@@ -0,0 +1,104 @@
+baidu:
+  token: 12313231232
+  back-domain: https://www.xxxx.com
+#配置
+logging:
+  level:
+    org.springframework.web: INFO
+    com.github.binarywang.demo.wx.cp: DEBUG
+    me.chanjar.weixin: DEBUG
+wx:
+  miniapp:
+    configs:
+      - appid: wxa6a215ad7353fd8a   #纯正堂药速通
+        secret: 4aa21869d9ed5bfc9477afb231a30f05 #纯正堂药速通
+        token: Ncbnd7lJvkripxxna6NAWCxCrvC
+        aesKey: HlEiBB55eaWUaeBVAQO3cWKWPYv1vOVQSq7nFNICw4E
+        msgDataFormat: JSON
+  cp:
+    corpId: wwa46ffb9ff6ac35b8 #企业ID北京存在文化
+    appConfigs:
+      - agentId: 1000070       #北京存在文化
+        secret: pu2EFz6gY2Fo2K-aRUxLPaAkKIaMJJRp8ES9JdpHkp4 #北京存在文化
+        token: PPKOdAlCoMO
+        aesKey: PKvaxtpSv8NGpfTDm7VUHIK8Wok2ESyYX24qpXJAdMP
+  pay:
+    appId:  #微信公众号或者小程序等的appid
+    mchId:  #微信支付商户号
+    mchKey:  #微信支付商户密钥
+    subAppId:  #服务商模式下的子商户公众账号ID
+    subMchId:  #服务商模式下的子商户号
+    keyPath: c:\\cert\\apiclient_cert.p12 # p12证书的位置,可以指定绝对路径,也可以指定类路径(以classpath:开头)
+    notifyUrl: https://userapp.his.runtzh.com/app/wxpay/wxPayNotify
+  mp:
+    useRedis: false
+    redisConfig:
+      host: 127.0.0.1
+      port: 6379
+      timeout: 2000
+    configs:
+      - appId: wx6d3706feab2b9926 # 第一个公众号的appid  //公众号名称:纯正堂大药房
+        secret: eedddc683062b258625f036a71d7cbc0 # 公众号的appsecret--纯正堂大药房
+        token: PPKOdAlCoMO # 接口配置里的Token值
+        aesKey: Eswa6VjwtVMCcw03qZy6fWllgrv5aytIA1SZPEU0kU2 # 接口配置里的EncodingAESKey值
+aifabu:  #爱链接
+  appKey: 7b471be905ab17e00f3b858c6710dd117601d008
+watch:
+  watchUrl: watch.ylrzcloud.com/prod-api
+  #  account: tcloud
+  #  password: mdf-m2h_6yw2$hq
+  account1: ccif #866655060138751
+  password1: cp-t5or_6xw7$mt
+  account2: tcloud #rt500台
+  password2: mdf-m2h_6yw2$hq
+  account3: whr
+  password3: v9xsKuqn_$d2y
+
+fs :
+  commonApi: http://127.0.0.1:7771
+  h5CommonApi: http://127.0.0.1:7771
+  jwt:
+    # 加密秘钥
+    secret: e10adc3949ba59abbe56e057f20f883e
+    # token有效时长,7天,单位秒
+    expire: 31536000
+    header: AppToken
+nuonuo:
+  key: 10924508
+  secret: A2EB20764D304D16
+
+# 存储捅配置
+tencent_cloud_config:
+  secret_id: AKIDiMq9lDf2EOM9lIfqqfKo7FNgM5meD0sT
+  secret_key: u5SuS80342xzx8FRBukza9lVNHKNMSaB
+  bucket: czt-1323137866
+  app_id: 1323137866
+  region: ap-chongqing
+  proxy: czt
+tmp_secret_config:
+  secret_id: AKIDCj7NSNAovtqeJpBau8GZ4CGB71thXIxX
+  secret_key: lTB5zwqqz7CNhzDOWivFWedgfTBgxgBT
+  bucket: fs-1319721001
+  app_id: 1319721001
+  region: ap-chongqing
+  proxy: fs
+cloud_host:
+  company_name: 纯正堂
+  projectCode: CZT
+headerImg:
+  imgUrl:
+
+ipad:
+  ipadUrl: http://ipad.cykbja.cn
+  aiApi: 1212121212
+  commonApi:
+  voiceApi:
+wx_miniapp_temp:
+  pay_order_temp_id:
+  inquiry_temp_id:
+
+# 0 代表关闭 1代表开启(润天老商户号的扣款限制)
+enableRedPackAccount: 0
+video:
+  videoUploadDir:
+  frameOutputDir:

+ 157 - 0
fs-service/src/main/resources/application-dev-czt.yml

@@ -0,0 +1,157 @@
+# 数据源配置
+spring:
+    profiles:
+        include: config-dev-czt,common
+    # redis 配置
+    redis:
+        host: localhost
+        port: 6379
+        # 数据库索引
+        database: 0
+        # 密码
+        password:
+        # 连接超时时间
+        timeout: 10s
+        lettuce:
+            pool:
+                # 连接池中的最小空闲连接
+                min-idle: 0
+                # 连接池中的最大空闲连接
+                max-idle: 8
+                # 连接池的最大数据库连接数
+                max-active: 100
+                # #连接池最大阻塞等待时间(使用负值表示没有限制)
+                max-wait: -1ms
+    datasource:
+#        clickhouse:
+#            type: com.alibaba.druid.pool.DruidDataSource
+#            driverClassName: com.clickhouse.jdbc.ClickHouseDriver
+#            url: jdbc:clickhouse://1.14.104.71:8123/sop_test?compress=0&use_server_time_zone=true&use_client_time_zone=false&timezone=Asia/Shanghai
+#            username: rt_2024
+#            password: Yzx_19860213
+#            initialSize: 10
+#            maxActive: 100
+#            minIdle: 10
+#            maxWait: 6000
+        mysql:
+            type: com.alibaba.druid.pool.DruidDataSource
+            driverClassName: com.mysql.cj.jdbc.Driver
+            druid:
+                # 主库数据源
+                master:
+                  url: jdbc:mysql://nj-cdb-5rexc1if.sql.tencentcdb.com:28670/fs_his?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
+                  username: root
+                  password: Ylrz_1q2w3e4r5t6y
+                # 从库数据源
+                slave:
+                    # 从数据源开关/默认关闭
+                    enabled: false
+                    url:
+                    username:
+                    password:
+                # 初始连接数
+                initialSize: 5
+                # 最小连接池数量
+                minIdle: 10
+                # 最大连接池数量
+                maxActive: 20
+                # 配置获取连接等待超时的时间
+                maxWait: 60000
+                # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
+                timeBetweenEvictionRunsMillis: 60000
+                # 配置一个连接在池中最小生存的时间,单位是毫秒
+                minEvictableIdleTimeMillis: 300000
+                # 配置一个连接在池中最大生存的时间,单位是毫秒
+                maxEvictableIdleTimeMillis: 900000
+                # 配置检测连接是否有效
+                validationQuery: SELECT 1 FROM DUAL
+                testWhileIdle: true
+                testOnBorrow: false
+                testOnReturn: false
+                webStatFilter:
+                    enabled: true
+                statViewServlet:
+                    enabled: true
+                    # 设置白名单,不填则允许所有访问
+                    allow:
+                    url-pattern: /druid/*
+                    # 控制台管理用户名和密码
+                    login-username: fs
+                    login-password: 123456
+                filter:
+                    stat:
+                        enabled: true
+                        # 慢SQL记录
+                        log-slow-sql: true
+                        slow-sql-millis: 1000
+                        merge-sql: true
+                    wall:
+                        config:
+                            multi-statement-allow: true
+        sop:
+            type: com.alibaba.druid.pool.DruidDataSource
+            driverClassName: com.mysql.cj.jdbc.Driver
+            druid:
+                # 主库数据源
+                master:
+                    url: jdbc:mysql://nj-cdb-5rexc1if.sql.tencentcdb.com:28670/fs_his_sop?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
+                    username: root
+                    password: Ylrz_1q2w3e4r5t6y
+                # 初始连接数
+                initialSize: 5
+                # 最小连接池数量
+                minIdle: 10
+                # 最大连接池数量
+                maxActive: 20
+                # 配置获取连接等待超时的时间
+                maxWait: 60000
+                # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
+                timeBetweenEvictionRunsMillis: 60000
+                # 配置一个连接在池中最小生存的时间,单位是毫秒
+                minEvictableIdleTimeMillis: 300000
+                # 配置一个连接在池中最大生存的时间,单位是毫秒
+                maxEvictableIdleTimeMillis: 900000
+                # 配置检测连接是否有效
+                validationQuery: SELECT 1 FROM DUAL
+                testWhileIdle: true
+                testOnBorrow: false
+                testOnReturn: false
+                webStatFilter:
+                    enabled: true
+                statViewServlet:
+                    enabled: true
+                    # 设置白名单,不填则允许所有访问
+                    allow:
+                    url-pattern: /druid/*
+                    # 控制台管理用户名和密码
+                    login-username: fs
+                    login-password: 123456
+                filter:
+                    stat:
+                        enabled: true
+                        # 慢SQL记录
+                        log-slow-sql: true
+                        slow-sql-millis: 1000
+                        merge-sql: true
+                    wall:
+                        config:
+                            multi-statement-allow: true
+rocketmq:
+    name-server: rmq-16xj8o92zp.rocketmq.cd.qcloud.tencenttdmq.com:8080
+    producer:
+        group: my-producer-group
+        access-key: ak16xj8o92zp984557f83ba2 # 替换为实际的 accessKey
+        secret-key: sk2ff1c6b15b74b888 # 替换为实际的 secretKey
+    consumer:
+        group: common-group
+        access-key: ak16xj8o92zp984557f83ba2 # 替换为实际的 accessKey
+        secret-key: sk2ff1c6b15b74b888 # 替换为实际的 secretKey
+openIM:
+    secret: openIM123
+    userID: imAdmin
+    url: https://web.im.fbylive.com/api
+#是否使用新im
+im:
+    type: NONE
+#是否为新商户,新商户不走mpOpenId
+isNewWxMerchant: true

+ 13 - 0
fs-service/src/main/resources/mapper/course/FsUserCourseVideoMapper.xml

@@ -60,6 +60,7 @@
             <if test="userId != null "> and user_id = #{userId}</if>
             <if test="projectId != null "> and project_id = #{projectId}</if>
             <if test="userId != null "> and user_id = #{userId}</if>
+            <if test="isDel != null "> and is_del = #{isDel}</if>
         </where>
     </select>
 
@@ -387,6 +388,18 @@
         update fs_user_course_video set red_packet_money = #{redPacketMoney} where video_id = #{videoId}
     </update>
 
+    <update id="batchUpdateByVideoId">
+        UPDATE fs_user_course_video
+        SET course_sort =
+        <foreach collection="list" item="item" index="index" separator=" " open="CASE video_id" close="END">
+            WHEN #{item.videoId} THEN #{item.courseSort}
+        </foreach>
+        WHERE video_id IN
+        <foreach collection="list" item="item" index="index" open="(" close=")" separator=",">
+            #{item.videoId}
+        </foreach>
+    </update>
+
 
     <select id="selectByFileKey"  resultMap="FsUserCourseVideoResult">
         <include refid="selectFsUserCourseVideoVo"/>

+ 4 - 0
fs-service/src/main/resources/mapper/sop/SopUserLogsMapper.xml

@@ -207,6 +207,10 @@
         where a.start_time &lt;= Now()
           and a.status = 1
           and b.send_type != 4 and b.status in (2,3)
+        <if test="sopIds != null and !sopIds.isEmpty()">
+            and a.sop_id in
+            <foreach collection="sopIds" open="(" close=")" index="index" item="item" separator=",">#{item}</foreach>
+        </if>
     </select>
 
     <select id="meetsTheRatingByUserInfo"   resultMap="SopUserLogsResult">