Browse Source

Merge remote-tracking branch 'origin/master' into yfh_dev

yfh 12 hours ago
parent
commit
7b66051fcb
50 changed files with 1139 additions and 177 deletions
  1. 10 6
      fs-admin/src/main/java/com/fs/his/controller/FsUserController.java
  2. 93 0
      fs-common-api/src/main/resources/logback.xml
  3. 3 2
      fs-company-app/src/main/java/com/fs/app/controller/CompanyUserController.java
  4. 0 1
      fs-company-app/src/main/java/com/fs/app/controller/FsUserController.java
  5. 19 0
      fs-company-app/src/main/java/com/fs/app/controller/FsUserCourseVideoController.java
  6. 1 1
      fs-company-app/src/main/java/com/fs/app/controller/UserController.java
  7. 1 0
      fs-company/src/main/java/com/fs/company/controller/company/CompanyUserController.java
  8. 5 2
      fs-qw-task/src/main/java/com/fs/app/controller/CommonController.java
  9. 2 2
      fs-qw-task/src/main/java/com/fs/app/task/UserCourseWatchCountTask.java
  10. 1 1
      fs-qw-task/src/main/resources/application.yml
  11. 3 2
      fs-service/src/main/java/com/fs/company/mapper/CompanyUserMapper.java
  12. 2 1
      fs-service/src/main/java/com/fs/company/service/ICompanyUserService.java
  13. 1 1
      fs-service/src/main/java/com/fs/company/service/impl/CompanyTagUserServiceImpl.java
  14. 11 3
      fs-service/src/main/java/com/fs/company/service/impl/CompanyUserServiceImpl.java
  15. 6 0
      fs-service/src/main/java/com/fs/course/domain/FsCourseLink.java
  16. 7 0
      fs-service/src/main/java/com/fs/course/domain/FsCourseRealLink.java
  17. 2 0
      fs-service/src/main/java/com/fs/course/param/FsCourseWatchLogListParam.java
  18. 2 2
      fs-service/src/main/java/com/fs/course/service/impl/FsCourseLinkServiceImpl.java
  19. 25 8
      fs-service/src/main/java/com/fs/course/service/impl/FsUserCourseServiceImpl.java
  20. 48 16
      fs-service/src/main/java/com/fs/course/service/impl/FsUserCourseVideoServiceImpl.java
  21. 1 0
      fs-service/src/main/java/com/fs/his/mapper/FsDoctorMapper.java
  22. 2 0
      fs-service/src/main/java/com/fs/his/mapper/FsPackageMapper.java
  23. 4 0
      fs-service/src/main/java/com/fs/his/mapper/FsUserDoctorMapper.java
  24. 7 0
      fs-service/src/main/java/com/fs/his/service/IFsPackageService.java
  25. 3 0
      fs-service/src/main/java/com/fs/his/service/IFsUserDoctorService.java
  26. 6 0
      fs-service/src/main/java/com/fs/his/service/impl/FsPackageServiceImpl.java
  27. 6 0
      fs-service/src/main/java/com/fs/his/service/impl/FsUserDoctorServiceImpl.java
  28. 63 32
      fs-service/src/main/java/com/fs/his/service/impl/FsUserServiceImpl.java
  29. 43 39
      fs-service/src/main/java/com/fs/qw/service/impl/QwExternalContactServiceImpl.java
  30. 12 0
      fs-service/src/main/java/com/fs/store/domain/FsUserCourseCount.java
  31. 6 0
      fs-service/src/main/java/com/fs/store/mapper/FsUserCourseCountMapper.java
  32. 17 0
      fs-service/src/main/java/com/fs/store/service/impl/FsUserCourseCountServiceImpl.java
  33. 3 1
      fs-service/src/main/java/com/fs/store/vo/h5/UserDetailsVO.java
  34. 94 0
      fs-service/src/main/resources/application-config-druid-bnkc.yml
  35. 2 9
      fs-service/src/main/resources/application-config-druid-fcky.yml
  36. 2 2
      fs-service/src/main/resources/application-config-druid-jzzx.yml
  37. 79 0
      fs-service/src/main/resources/application-config-druid-lmjy.yml
  38. 149 0
      fs-service/src/main/resources/application-druid-bnkc.yml
  39. 150 0
      fs-service/src/main/resources/application-druid-lmjy.yml
  40. 2 2
      fs-service/src/main/resources/application-druid-whhm.yml
  41. 13 4
      fs-service/src/main/resources/mapper/company/CompanyUserMapper.xml
  42. 7 1
      fs-service/src/main/resources/mapper/course/FsCourseWatchLogMapper.xml
  43. 6 0
      fs-service/src/main/resources/mapper/course/FsUserCourseMapper.xml
  44. 7 0
      fs-service/src/main/resources/mapper/his/FsPackageMapper.xml
  45. 28 24
      fs-service/src/main/resources/mapper/his/FsUserMapper.xml
  46. 33 15
      fs-service/src/main/resources/mapper/store/FsUserCourseCountMapper.xml
  47. 6 0
      fs-user-app/src/main/java/com/fs/app/controller/DoctorController.java
  48. 7 0
      fs-user-app/src/main/java/com/fs/app/controller/PackageController.java
  49. 129 0
      fs-user-app/src/main/java/com/fs/app/controller/WxH5MpController.java
  50. 10 0
      fs-user-app/src/main/java/com/fs/app/param/FsUserLoginByMpParam.java

+ 10 - 6
fs-admin/src/main/java/com/fs/his/controller/FsUserController.java

@@ -4,6 +4,7 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
+import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
 import com.fs.common.core.domain.R;
 import com.fs.common.core.domain.ResponseResult;
 import com.fs.common.utils.ParseUtils;
@@ -198,13 +199,16 @@ public class FsUserController extends BaseController
 //        startPage();
         PageHelper.startPage(param.getPageNum(), param.getPageSize());
         PageInfo<FsUserPageListVO> fsUserPageListVOPageInfo = fsUserService.selectFsUserPageList(param);
-        for (FsUserPageListVO fsUserPageListVO : fsUserPageListVOPageInfo.getList()) {
-            fsUserPageListVO.setPhone(ParseUtils.parsePhone(fsUserPageListVO.getPhone()));
+        if(ObjectUtils.isNotNull(fsUserPageListVOPageInfo)){
+            for (FsUserPageListVO fsUserPageListVO : fsUserPageListVOPageInfo.getList()) {
+                fsUserPageListVO.setPhone(ParseUtils.parsePhone(fsUserPageListVO.getPhone()));
+            }
+            Map<String, Object> map = new HashMap<String, Object>();
+            map.put("rows", fsUserPageListVOPageInfo.getList());
+            map.put("total", fsUserPageListVOPageInfo.getList().size());
+            return R.ok(map);
         }
-        Map<String, Object> map = new HashMap<String, Object>();
-        map.put("rows", fsUserPageListVOPageInfo.getList());
-        map.put("total", fsUserPageListVOPageInfo.getList().size());
-        return R.ok(map);
+        return R.ok();
     }
 
     @PreAuthorize("@ss.hasPermi('his:user:enabledUsers')")

+ 93 - 0
fs-common-api/src/main/resources/logback.xml

@@ -0,0 +1,93 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<configuration>
+    <!-- 日志存放路径 -->
+	<property name="log.path" value="/home/fs-common-api/logs" />
+    <!-- 日志输出格式 -->
+	<property name="log.pattern" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %msg%n" />
+
+	<!-- 控制台输出 -->
+	<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
+		<encoder>
+			<pattern>${log.pattern}</pattern>
+		</encoder>
+	</appender>
+
+	<!-- 系统日志输出 -->
+	<appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender">
+	    <file>${log.path}/sys-info.log</file>
+        <!-- 循环政策:基于时间创建日志文件 -->
+		<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <!-- 日志文件名格式 -->
+			<fileNamePattern>${log.path}/sys-info.%d{yyyy-MM-dd}.log</fileNamePattern>
+			<!-- 日志最大的历史 30 -->
+			<maxHistory>30</maxHistory>
+		</rollingPolicy>
+		<encoder>
+			<pattern>${log.pattern}</pattern>
+		</encoder>
+		<filter class="ch.qos.logback.classic.filter.LevelFilter">
+            <!-- 过滤的级别 -->
+            <level>INFO</level>
+            <!-- 匹配时的操作:接收(记录) -->
+            <onMatch>ACCEPT</onMatch>
+            <!-- 不匹配时的操作:拒绝(不记录) -->
+            <onMismatch>DENY</onMismatch>
+        </filter>
+	</appender>
+
+	<appender name="file_error" class="ch.qos.logback.core.rolling.RollingFileAppender">
+	    <file>${log.path}/sys-error.log</file>
+        <!-- 循环政策:基于时间创建日志文件 -->
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <!-- 日志文件名格式 -->
+            <fileNamePattern>${log.path}/sys-error.%d{yyyy-MM-dd}.log</fileNamePattern>
+			<!-- 日志最大的历史 30 -->
+			<maxHistory>30</maxHistory>
+        </rollingPolicy>
+        <encoder>
+            <pattern>${log.pattern}</pattern>
+        </encoder>
+        <filter class="ch.qos.logback.classic.filter.LevelFilter">
+            <!-- 过滤的级别 -->
+            <level>ERROR</level>
+			<!-- 匹配时的操作:接收(记录) -->
+            <onMatch>ACCEPT</onMatch>
+			<!-- 不匹配时的操作:拒绝(不记录) -->
+            <onMismatch>DENY</onMismatch>
+        </filter>
+    </appender>
+
+	<!-- 用户访问日志输出  -->
+    <appender name="sys-user" class="ch.qos.logback.core.rolling.RollingFileAppender">
+		<file>${log.path}/sys-user.log</file>
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <!-- 按天回滚 daily -->
+            <fileNamePattern>${log.path}/sys-user.%d{yyyy-MM-dd}.log</fileNamePattern>
+            <!-- 日志最大的历史 30 -->
+            <maxHistory>30</maxHistory>
+        </rollingPolicy>
+        <encoder>
+            <pattern>${log.pattern}</pattern>
+        </encoder>
+    </appender>
+
+	<!-- 系统模块日志级别控制  -->
+	<logger name="com.fs" level="info" />
+	<!-- Spring日志级别控制  -->
+	<logger name="org.springframework" level="warn" />
+
+	<root level="info">
+		<appender-ref ref="console" />
+	</root>
+
+	<!--系统操作日志-->
+    <root level="info">
+        <appender-ref ref="file_info" />
+        <appender-ref ref="file_error" />
+    </root>
+
+	<!--系统用户操作日志-->
+    <logger name="sys-user" level="info">
+        <appender-ref ref="sys-user"/>
+    </logger>
+</configuration>

+ 3 - 2
fs-company-app/src/main/java/com/fs/app/controller/CompanyUserController.java

@@ -73,12 +73,12 @@ public class CompanyUserController extends AppBaseController {
         // 判断是否管理员 或者包含 1:全部数据权限
         if (companyUser.isAdmin() || companyRoles.stream().anyMatch(r -> "1".equals(r.getDataScope()))) {
             PageHelper.startPage(pageNum, pageSize);
-            companyUsers = companyUserService.getCompanyUserListByDeptId(null);
+            companyUsers = companyUserService.getCompanyUserListByCompanyIdAndDeptId(companyUser.getCompanyId(), null);
         }
         // 判断是否包含 3:本部门数据权限 4:本部门及以下数据权限
         else if (companyRoles.stream().anyMatch(r -> "3".equals(r.getDataScope()) || "4".equals(r.getDataScope()))) {
             PageHelper.startPage(pageNum, pageSize);
-            companyUsers = companyUserService.getCompanyUserListByDeptId(companyUser.getDeptId());
+            companyUsers = companyUserService.getCompanyUserListByCompanyIdAndDeptId(companyUser.getCompanyId(), companyUser.getDeptId());
         }
         // 默认空 -- 判断是否包含 5:仅可查看本人
         else {
@@ -190,6 +190,7 @@ public class CompanyUserController extends AppBaseController {
         BeanUtils.copyProperties(param, companyUser);
 
         companyUser.setUserName(param.getPhoneNumber());
+        companyUser.setUserType("01");
         companyUser.setPhonenumber(param.getPhoneNumber());
         companyUser.setPassword(SecurityUtils.encryptPassword(companyUser.getPassword()));
         companyUser.setCreateTime(new Date());

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

@@ -77,7 +77,6 @@ public class FsUserController extends AppBaseController {
         param.setUserId(Long.parseLong(getUserId()));
         PageHelper.startPage(param.getPageNum(), param.getPageSize());
         PageInfo<FsUserPageListVO> fsUserPageListVOPageInfo = fsUserService.selectFsUserPageList(param);
-//        PageInfo<FsUserPageListVO> pageInfo = new PageInfo<>(list);
         return ResponseResult.ok(fsUserPageListVOPageInfo);
     }
 

+ 19 - 0
fs-company-app/src/main/java/com/fs/app/controller/FsUserCourseVideoController.java

@@ -4,7 +4,11 @@ import com.fs.app.annotation.Login;
 import com.fs.app.config.ImageStorageConfig;
 import com.fs.common.core.domain.R;
 import com.fs.common.core.domain.ResponseResult;
+import com.fs.common.enums.BizResponseEnum;
 import com.fs.common.utils.StringUtils;
+import com.fs.company.domain.CompanyUser;
+import com.fs.company.service.ICompanyUserService;
+import com.fs.company.service.impl.CompanyServiceImpl;
 import com.fs.course.domain.FsUserCoursePeriod;
 import com.fs.course.param.FsCourseLinkCreateParam;
 import com.fs.course.param.FsWatchCourseTimeParam;
@@ -58,6 +62,8 @@ public class FsUserCourseVideoController extends AppBaseController {
 
     @Autowired
     private IFsUserCoursePeriodService fsUserCoursePeriodService;
+    @Autowired
+    private ICompanyUserService companyService;
 
     @Login
     @GetMapping("/pageList")
@@ -109,11 +115,24 @@ public class FsUserCourseVideoController extends AppBaseController {
                                                       @RequestParam(required = false, defaultValue = "1") Integer pageNum,
                                                       @RequestParam(required = false, defaultValue = "10") Integer pageSize) {
         log.debug("参与记录 keyword: {}, pageNum: {}, pageSize: {}", keyword, pageNum, pageSize);
+        String userId = getUserId();
         Map<String, Object> params = new HashMap<>();
+        //判断是否管理员 管理员查所有
+        CompanyUser companyUser = companyService.selectCompanyUserById(Long.valueOf(userId));
+        if (companyUser != null) {
+            if (companyUser.isAdmin()) {
+                params.put("companyId", companyUser.getCompanyId());
+            } else {
+                params.put("companyUserId", userId);
+            }
+        } else {
+            return ResponseResult.fail(BizResponseEnum.PARAM_ERROR);
+        }
         params.put("videoId", videoId);
         params.put("type", type);
         params.put("keyword", keyword);
 
+
         PageHelper.startPage(pageNum, pageSize);
         List<FsUserCourseParticipationRecordVO> record = fsUserCourseService.getParticipationRecordByMap(params);
         return ResponseResult.ok(new PageInfo<>(record));

+ 1 - 1
fs-company-app/src/main/java/com/fs/app/controller/UserController.java

@@ -257,7 +257,7 @@ public class UserController extends AppBaseController {
             companyUser.setCompanyName(company.getCompanyName());
             // 岗位
             companyUser.setPosts(postService.selectCompanyPostListByUserId(companyUser.getUserId()));
-            return R.ok().put("user", companyUser);
+            return R.ok().put("user", companyUser).put("balance", company.getMoney());
         } catch (Exception e) {
 
             return R.error("操作异常");

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

@@ -192,6 +192,7 @@ public class CompanyUserController extends BaseController
         user.setPassword(SecurityUtils.encryptPassword(user.getPassword()));
         user.setCreateTime(new Date());
         user.setUserType("01");//一般用户
+        user.setIsAudit(1);
         return toAjax(companyUserService.insertUser(user));
     }
 

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

@@ -20,6 +20,7 @@ import com.fs.sop.mapper.QwSopMapper;
 import com.fs.sop.mapper.SopUserLogsMapper;
 import com.fs.sop.service.*;
 import com.fs.sop.vo.QwSopLogsDoSendListTVO;
+import com.fs.store.service.IFsUserCourseCountService;
 import io.swagger.annotations.Api;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -82,6 +83,9 @@ public class CommonController {
     @Autowired
     private ISopUserLogsService iSopUserLogsService;
 
+    @Autowired
+    private IFsUserCourseCountService userCourseCountService;
+
 
     @GetMapping("/testSop")
     public R testSop() throws Exception {
@@ -194,8 +198,7 @@ public class CommonController {
     private SopLogsChatTaskService sopLogsChatTaskService;
     @GetMapping("/test2")
     public String selectChatSopUserLogsListByTime() throws Exception {
-        System.out.println("test2");
-       // sopLogsChatTaskService.createAiChatSopLogs();
+        userCourseCountService.insertFsUserCourseCountTask();
         return "s";
     }
 

+ 2 - 2
fs-qw-task/src/main/java/com/fs/app/task/UserCourseWatchCountTask.java

@@ -14,9 +14,9 @@ public class UserCourseWatchCountTask {
 
 
     /**
-     * 每天两点进行会员看课统计
+     * 每15分钟执行一次
      */
-    @Scheduled(cron = "0 0 2 * * ?")  // 2点0分0秒执行
+    @Scheduled(cron = "0 */15 * * * ?")  // 每15分钟执行一次
     public void userCourseCountTask() {
         try {
             log.info("==============会员看课统计任务执行===============开始");

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

@@ -10,4 +10,4 @@ spring:
 #    active: druid-hcl
 #    active: druid-sxjz
 #    active: druid-hdt
-    active: druid-myhk
+    active: druid-fcky-test

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

@@ -214,7 +214,7 @@ public interface CompanyUserMapper
     @Select("select domain from company_user where user_id = #{userId}")
     String selectDomainByUserId(Long userId);
 
-    List<CompanyUser> selectAllCompanyUserAndSelf(@Param("userId") Long userId);
+    List<CompanyUser> selectAllCompanyUserAndSelf(@Param("userId") Long userId,@Param("companyId") Long companyId);
 
     @Select("select * from company_user where company_id=#{companyId} and del_flag=0")
     List<CompanyUser> selectCompanyUserByCompanyId(Long companyId);
@@ -233,10 +233,11 @@ public interface CompanyUserMapper
 
     /**
      * 根据部门ID查询销售列表
+     * @param companyId 公司ID
      * @param deptId    部门ID
      * @return  list
      */
-    List<CompanyUser> selectAllCompanyUserByDeptId(@Param("deptId") Long deptId);
+    List<CompanyUser> selectAllCompanyUserByCompanyIdAndDeptId(@Param("companyId") Long companyId, @Param("deptId") Long deptId);
 
     @Select("select * from company_user where ma_open_id = #{maOpenId}")
     CompanyUser getCompanyUserByOpenId(String openId);

+ 2 - 1
fs-service/src/main/java/com/fs/company/service/ICompanyUserService.java

@@ -151,10 +151,11 @@ public interface ICompanyUserService {
 
     /**
      * 查询销售列表
+     * @param companyId 公司ID
      * @param deptId 部门ID
      * @return list
      */
-    List<CompanyUser> getCompanyUserListByDeptId(Long deptId);
+    List<CompanyUser> getCompanyUserListByCompanyIdAndDeptId(Long companyId, Long deptId);
 
     /**
      * 根据openid获取销售

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

@@ -118,7 +118,7 @@ public class CompanyTagUserServiceImpl implements ICompanyTagUserService
             }
         }
         //获取所有销售
-        List<CompanyUser> companyUsers = companyUserMapper.selectAllCompanyUserAndSelf(param != null ? param.getUserId() : null);
+        List<CompanyUser> companyUsers = companyUserMapper.selectAllCompanyUserAndSelf(param != null ? param.getUserId() : null,null);
         List<Long> userIds = Collections.emptyList();
         if(companyUsers != null && !companyUsers.isEmpty()){
             userIds = companyUsers.stream().map(CompanyUser::getUserId).collect(Collectors.toList());

+ 11 - 3
fs-service/src/main/java/com/fs/company/service/impl/CompanyUserServiceImpl.java

@@ -452,17 +452,25 @@ public class CompanyUserServiceImpl implements ICompanyUserService
 
     @Override
     public List<CompanyUser> selectAllCompanyUserAndSelf(Long userId) {
-        return companyUserMapper.selectAllCompanyUserAndSelf(userId);
+        CompanyUser companyUser = companyUserMapper.selectCompanyUserById(userId);
+        List<CompanyUser> list = new ArrayList<>();
+        if (companyUser.isAdmin()){
+            list = companyUserMapper.selectAllCompanyUserAndSelf(userId,companyUser.getCompanyId());
+        }else {
+            list =   companyUserMapper.selectAllCompanyUserAndSelf(userId,null);
+        }
+        return list;
     }
 
     /**
      * 查询销售列表
+     * @param companyId 公司ID
      * @param deptId 部门ID
      * @return list
      */
     @Override
-    public List<CompanyUser> getCompanyUserListByDeptId(Long deptId) {
-        return companyUserMapper.selectAllCompanyUserByDeptId(deptId);
+    public List<CompanyUser> getCompanyUserListByCompanyIdAndDeptId(Long companyId, Long deptId) {
+        return companyUserMapper.selectAllCompanyUserByCompanyIdAndDeptId(companyId, deptId);
     }
 
     @Override

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

@@ -2,6 +2,7 @@ package com.fs.course.domain;
 
 import com.fs.common.annotation.Excel;
 import com.fs.common.core.domain.BaseEntity;
+import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 
 /**
@@ -57,6 +58,11 @@ public class FsCourseLink extends BaseEntity
     private Integer isRoom;//是否发群
     private String chatId;//是否发群
 
+    private Long periodId;
+
+    @ApiModelProperty(value = "营期课程id")
+    private Long id;
+
 //    private String link_uuid;
 
 }

+ 7 - 0
fs-service/src/main/java/com/fs/course/domain/FsCourseRealLink.java

@@ -2,6 +2,7 @@ package com.fs.course.domain;
 
 import com.fs.common.annotation.Excel;
 import com.fs.common.core.domain.BaseEntity;
+import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 
 import java.io.Serializable;
@@ -36,4 +37,10 @@ public class FsCourseRealLink implements Serializable
     private Integer isRoom;
     private Long fsUserId;
 
+    private Long periodId;
+
+    @ApiModelProperty(value = "营期课程id")
+    private Long id;
+
+
 }

+ 2 - 0
fs-service/src/main/java/com/fs/course/param/FsCourseWatchLogListParam.java

@@ -35,6 +35,8 @@ public class FsCourseWatchLogListParam implements Serializable {
 
     private String sopDate;
 
+    private Integer sendType;
+
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     private Date eTime;
 

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

@@ -533,14 +533,14 @@ public class FsCourseLinkServiceImpl implements IFsCourseLinkService
                         return R.error("真实链接不存在").put("realLink", sLink);
                     }
                     log.info("链接仍然有效: {}", sLink);
-                    String json = configService.selectConfigByKey("h5.course.config");
+                    String json = configService.selectConfigByKey("course.config");
                     CourseConfig config = JSONUtil.toBean(json, CourseConfig.class);
                     String domainName = companyUserMapper.selectDomainByUserId(courseLink.getCompanyUserId());
                     if (StringUtils.isEmpty(domainName)){
                         domainName = config.getRealLinkDomainName();
                     }
                     String realLink = domainName+courseLink.getRealLink();
-                    String imgUrl = "";
+                    String imgUrl = cloudHostProper.getHeaderImg();
                     return R.ok().put("realLink",realLink ).put("config",config).put("headerImg",imgUrl);
                 }
             } else {

+ 25 - 8
fs-service/src/main/java/com/fs/course/service/impl/FsUserCourseServiceImpl.java

@@ -650,20 +650,37 @@ public class FsUserCourseServiceImpl implements IFsUserCourseService
         }
         return domainName;
     }
+
     public static String generateRandomString() {
         return FsCourseLinkServiceImpl.generateRandomString();
     }
+
     private static Calendar getExpireDay(FsCourseLinkCreateParam param, CourseConfig config, Date createTime) {
-        Integer expireDuration;
-        if (param.getEffectiveDuration() == null || param.getEffectiveDuration() == 0){
-            expireDuration = config.getVideoLinkExpireDate();
-        }else {
-            expireDuration = param.getEffectiveDuration();
+        if (param == null || config == null || createTime == null) {
+            throw new IllegalArgumentException("Parameters cannot be null");
         }
-        // 设置过期时间
+
         Calendar calendar = Calendar.getInstance();
-        calendar.setTime(createTime);
-        calendar.add(Calendar.MINUTE, expireDuration);
+
+        if (param.getEffectiveDuration() == null || param.getEffectiveDuration() == 0) {
+            // 未传时间分钟的走配置,当天24:00(次日0:00)过期
+            Integer expireDays = config.getVideoLinkExpireDate() != null ? config.getVideoLinkExpireDate() : 1; // 默认1天
+
+            Date baseDate = param.getSendTime() != null ? param.getSendTime() : createTime;
+            calendar.setTime(baseDate);
+            calendar.add(Calendar.DAY_OF_MONTH, expireDays);
+
+            // 设置为次日0:00(即当天的24:00)
+            calendar.set(Calendar.HOUR_OF_DAY, 0);
+            calendar.set(Calendar.MINUTE, 0);
+            calendar.set(Calendar.SECOND, 0);
+            calendar.set(Calendar.MILLISECOND, 0);
+        } else {
+            // 传入时间分钟的
+            calendar.setTime(createTime);
+            calendar.add(Calendar.MINUTE, param.getEffectiveDuration());
+        }
+
         return calendar;
     }
     /**

+ 48 - 16
fs-service/src/main/java/com/fs/course/service/impl/FsUserCourseVideoServiceImpl.java

@@ -877,17 +877,45 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
 
         System.out.println("红包商户号"+amount);
         System.out.println("红包商户号"+packetParam);
-        // 发送红包
-        R sendRedPacket = paymentService.sendRedPacket(packetParam);
-        if (sendRedPacket.get("code").equals(200)) {
-            FsCourseRedPacketLog redPacketLog = new FsCourseRedPacketLog();
-            TransferBillsResult transferBillsResult;
-            if (sendRedPacket.get("isNew").equals(1)){
-                transferBillsResult = (TransferBillsResult)sendRedPacket.get("data");
-                redPacketLog.setOutBatchNo(transferBillsResult.getOutBillNo());
-            }else {
-                redPacketLog.setOutBatchNo(sendRedPacket.get("orderCode").toString());
+        //2025.6.19 红包金额为0的时候
+        if (amount.compareTo(BigDecimal.ZERO)>0){
+            // 发送红包
+            R sendRedPacket = paymentService.sendRedPacket(packetParam);
+            if (sendRedPacket.get("code").equals(200)) {
+                FsCourseRedPacketLog redPacketLog = new FsCourseRedPacketLog();
+                TransferBillsResult transferBillsResult;
+                if (sendRedPacket.get("isNew").equals(1)){
+                    transferBillsResult = (TransferBillsResult)sendRedPacket.get("data");
+                    redPacketLog.setOutBatchNo(transferBillsResult.getOutBillNo());
+                }else {
+                    redPacketLog.setOutBatchNo(sendRedPacket.get("orderCode").toString());
+                }
+                // 添加红包记录
+                redPacketLog.setCourseId(param.getCourseId());
+//            redPacketLog.setOutBatchNo(sendRedPacket.get("orderCode").toString());
+                redPacketLog.setCompanyId(param.getCompanyId());
+                redPacketLog.setUserId(param.getUserId());
+                redPacketLog.setVideoId(param.getVideoId());
+                redPacketLog.setStatus(0);
+                redPacketLog.setQwUserId(param.getQwUserId() != null ? param.getQwUserId() : null);
+                redPacketLog.setCompanyUserId(param.getCompanyUserId());
+                redPacketLog.setCreateTime(new Date());
+                redPacketLog.setAmount(amount);
+                redPacketLog.setWatchLogId(log.getLogId() != null ? log.getLogId() : null);
+                redPacketLog.setPeriodId(param.getPeriodId());
+                redPacketLogMapper.insertFsCourseRedPacketLog(redPacketLog);
+
+                // 更新观看记录的奖励类型
+//            if (param.getLinkType() == null || param.getLinkType() == 0) {
+                log.setRewardType(config.getRewardType());
+                courseWatchLogMapper.updateFsCourseWatchLog(log);
+//            }
+                return sendRedPacket;
+            } else {
+                return R.error("奖励发送失败,请联系客服");
             }
+        } else {
+            FsCourseRedPacketLog redPacketLog = new FsCourseRedPacketLog();
             // 添加红包记录
             redPacketLog.setCourseId(param.getCourseId());
 //            redPacketLog.setOutBatchNo(sendRedPacket.get("orderCode").toString());
@@ -898,7 +926,7 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
             redPacketLog.setQwUserId(param.getQwUserId() != null ? param.getQwUserId() : null);
             redPacketLog.setCompanyUserId(param.getCompanyUserId());
             redPacketLog.setCreateTime(new Date());
-            redPacketLog.setAmount(amount);
+            redPacketLog.setAmount(BigDecimal.ZERO);
             redPacketLog.setWatchLogId(log.getLogId() != null ? log.getLogId() : null);
             redPacketLog.setPeriodId(param.getPeriodId());
             redPacketLogMapper.insertFsCourseRedPacketLog(redPacketLog);
@@ -908,10 +936,9 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
             log.setRewardType(config.getRewardType());
             courseWatchLogMapper.updateFsCourseWatchLog(log);
 //            }
-            return sendRedPacket;
-        } else {
-            return R.error("奖励发送失败,请联系客服");
+            return R.ok("红包发送成功");
         }
+
     }
 
     /**
@@ -1094,8 +1121,8 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
 
         // 如果开启了黑名单审核,需要提示
         if(fsUser.getStatus() == 0) {
-//            return ResponseResult.fail(505, "管理开启了会员审核,请等待审核");
-            return ResponseResult.fail(BizResponseEnum.WAIT_APPROVAL,getCompanyUserQRCode(companyUser));
+            return ResponseResult.fail(505, "请微信联系您的群主~");
+//            return ResponseResult.fail(BizResponseEnum.WAIT_APPROVAL,getCompanyUserQRCode(companyUser));
         }
 
         //查询看课记录
@@ -1129,6 +1156,11 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
             fsCourseWatchLog.setLogType(1);
             fsCourseWatchLog.setProject(courseProject);
             courseWatchLogMapper.insertFsCourseWatchLog(fsCourseWatchLog);
+
+            String redisKey = "h5wxuser:watch:heartbeat:" + param.getUserId() + ":" + param.getVideoId() + ":" + param.getCompanyUserId();
+            redisCache.setCacheObject(redisKey, LocalDateTime.now().toString());
+            // 设置 Redis 记录的过期时间(例如 5 分钟)
+            redisCache.expire(redisKey, 300, TimeUnit.SECONDS);
         }
 
         // 添加会员销售关系表数据

+ 1 - 0
fs-service/src/main/java/com/fs/his/mapper/FsDoctorMapper.java

@@ -166,6 +166,7 @@ public interface FsDoctorMapper
             " order by d.sort desc "+
             "</script>"})
     List<FsDoctorListUVO> selectFsDoctorListUVO(@Param("maps") FsDoctorListUParam param);
+
     @Select("select * from fs_doctor where account=#{account}")
     FsDoctor selectFsDoctorByAccount(String account);
     @Select("select * from fs_doctor where user_id=#{userId}")

+ 2 - 0
fs-service/src/main/java/com/fs/his/mapper/FsPackageMapper.java

@@ -139,4 +139,6 @@ public interface FsPackageMapper
             "</foreach>"+
             "</script>"})
     int updatePackagesStatus(@Param("packageIds")Long[] packageIds,@Param("status")Long status);
+
+    List<String> selectIcdNameByPackageId(@Param("packageId")Long packageId);
 }

+ 4 - 0
fs-service/src/main/java/com/fs/his/mapper/FsUserDoctorMapper.java

@@ -3,6 +3,7 @@ package com.fs.his.mapper;
 import java.util.List;
 
 import com.fs.common.core.domain.R;
+import com.fs.his.domain.FsDoctor;
 import com.fs.his.domain.FsUserDoctor;
 import com.fs.his.param.FsUserDoctorListUParam;
 import com.fs.his.vo.FsUserDoctorListUVO;
@@ -85,4 +86,7 @@ public interface FsUserDoctorMapper
     int checkFollow(@Param("doctorId") Long doctorId,@Param("userId")long userId);
     @Delete("delete from fs_user_doctor  where type=1 and doctor_id=#{doctorId} and user_id=#{userId} ")
     int deleteFollow(@Param("doctorId") Long doctorId,@Param("userId")long userId);
+
+    @Select("select doctor_name as doctorName,avatar as avatar from fs_doctor where is_agreement_prescribe_doctor = 1 ORDER BY RAND() LIMIT 1")
+    FsDoctor getAgreement();
 }

+ 7 - 0
fs-service/src/main/java/com/fs/his/service/IFsPackageService.java

@@ -79,4 +79,11 @@ public interface IFsPackageService
     int updatePackagesStatus(Long[] packageIds, Long status);
 
     String convertImageToJpg(String imgUrl, Long packageId);
+
+    /**
+     * 根据套餐id查询icd名字
+     * @param packageId
+     * @return icdName
+     */
+    List<String> selectIcdNameByPackageId(Long packageId);
 }

+ 3 - 0
fs-service/src/main/java/com/fs/his/service/IFsUserDoctorService.java

@@ -3,6 +3,7 @@ package com.fs.his.service;
 import java.util.List;
 
 import com.fs.common.core.domain.R;
+import com.fs.his.domain.FsDoctor;
 import com.fs.his.domain.FsUserDoctor;
 import com.fs.his.param.FsUserDoctorListUParam;
 import com.fs.his.vo.FsUserDoctorListUVO;
@@ -69,4 +70,6 @@ public interface IFsUserDoctorService
     R checkFollow(Long doctorId, long userId);
 
     int deleteFollow(Long doctorId, long userId);
+
+    FsDoctor getAgreement();
 }

+ 6 - 0
fs-service/src/main/java/com/fs/his/service/impl/FsPackageServiceImpl.java

@@ -5,6 +5,7 @@ import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.math.BigDecimal;
 import java.net.URL;
+import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 
@@ -293,5 +294,10 @@ public class FsPackageServiceImpl implements IFsPackageService {
         }
         return null;
     }
+
+    @Override
+    public List<String> selectIcdNameByPackageId(Long packageId) {
+        return fsPackageMapper.selectIcdNameByPackageId(packageId);
+    }
 }
 

+ 6 - 0
fs-service/src/main/java/com/fs/his/service/impl/FsUserDoctorServiceImpl.java

@@ -3,6 +3,7 @@ package com.fs.his.service.impl;
 import java.util.List;
 
 import com.fs.common.core.domain.R;
+import com.fs.his.domain.FsDoctor;
 import com.fs.his.param.FsUserDoctorListUParam;
 import com.fs.his.vo.FsUserDoctorListUVO;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -109,4 +110,9 @@ public class FsUserDoctorServiceImpl implements IFsUserDoctorService
     public int deleteFollow(Long doctorId, long userId) {
         return fsUserDoctorMapper.deleteFollow(doctorId,userId);
     }
+
+    @Override
+    public FsDoctor getAgreement() {
+        return fsUserDoctorMapper.getAgreement();
+    }
 }

+ 63 - 32
fs-service/src/main/java/com/fs/his/service/impl/FsUserServiceImpl.java

@@ -22,14 +22,8 @@ import com.fs.common.utils.ParseUtils;
 import com.fs.common.utils.StringUtils;
 import com.fs.company.cache.ICompanyTagCacheService;
 import com.fs.company.cache.ICompanyUserCacheService;
-import com.fs.company.domain.Company;
-import com.fs.company.domain.CompanyTag;
-import com.fs.company.domain.CompanyTagUser;
-import com.fs.company.domain.CompanyUser;
-import com.fs.company.mapper.CompanyMapper;
-import com.fs.company.mapper.CompanyTagMapper;
-import com.fs.company.mapper.CompanyTagUserMapper;
-import com.fs.company.mapper.CompanyUserMapper;
+import com.fs.company.domain.*;
+import com.fs.company.mapper.*;
 import com.fs.company.service.ICompanyTagService;
 import com.fs.course.domain.FsUserCompanyUser;
 import com.fs.course.mapper.FsUserCompanyUserMapper;
@@ -127,6 +121,9 @@ public class FsUserServiceImpl implements IFsUserService
     @Autowired
     private IQwExternalContactCacheService qwExternalContactCacheService;
 
+    @Autowired
+    private CompanyRoleMapper companyRoleMapper;
+
 
     /**
      * 查询用户
@@ -512,31 +509,58 @@ public class FsUserServiceImpl implements IFsUserService
 
     @Override
     public PageInfo<FsUserPageListVO> selectFsUserPageList(FsUserPageListParam param) {
-        List<FsUserPageListVO> fsUserPageListVOS = fsUserMapper.selectFsUserPageList(param);
+          CompanyUser companyUser = companyUserMapper.selectCompanyUserById(param.getUserId());
+
+//        List<CompanyRole> companyRoles = companyRoleMapper.selectRolePermissionByUserId(param.getUserId());
+//        List<CompanyUser> companyUsers;
+//        CompanyUser companyUser = companyUserMapper.selectCompanyUserById(param.getUserId());
+//        // 判断是否管理员 或者包含 1:全部数据权限
+//        if (companyUser.isAdmin() || companyRoles.stream().anyMatch(r -> "1".equals(r.getDataScope()))) {
+//            companyUsers = companyUserService.getCompanyUserListByCompanyIdAndDeptId(companyUser.getCompanyId(), null);
+//        }
+//        // 判断是否包含 3:本部门数据权限 4:本部门及以下数据权限
+//        else if (companyRoles.stream().anyMatch(r -> "3".equals(r.getDataScope()) || "4".equals(r.getDataScope()))) {
+//            companyUsers = companyUserService.getCompanyUserListByCompanyIdAndDeptId(companyUser.getCompanyId(), companyUser.getDeptId());
+//        }
+//        // 默认空 -- 判断是否包含 5:仅可查看本人
+//        else {
+//            companyUsers = new ArrayList<>();
+//        }
+
+        if(ObjectUtils.isNotNull(companyUser)){
+            if (companyUser.isAdmin()){
+                param.setUserId(0L);
+                param.setCompanyId(companyUser.getCompanyId());
+            }
 
-        // 获取当前销售所有重粉会员
-        List<FsUserCompanyUser> fsUserCompanyUsers = fsUserCompanyUserMapper.selectRepeatUser(param.getUserId());
+            List<FsUserPageListVO> fsUserPageListVOS = fsUserMapper.selectFsUserPageList(param);
+            // 获取当前销售所有重粉会员
+            List<FsUserCompanyUser> fsUserCompanyUsers = fsUserCompanyUserMapper.selectRepeatUser(companyUser.getUserId());
 
-        if(!fsUserCompanyUsers.isEmpty()){
-            List<Long> userIds = fsUserCompanyUsers.stream().map(FsUserCompanyUser::getUserId).collect(Collectors.toList());
-            // 获取会员所属的重粉销售
-            List<FsUserCompanyUser> repeatCompanyUserNames = fsUserCompanyUserMapper.selectRepeatCompanyUserName(userIds);
-            Map<Long, String> map = repeatCompanyUserNames.stream().collect(Collectors.toMap(FsUserCompanyUser::getUserId, FsUserCompanyUser::getRepeatCompanyUserName));
+            if(!fsUserCompanyUsers.isEmpty()){
+                List<Long> userIds = fsUserCompanyUsers.stream().map(FsUserCompanyUser::getUserId).collect(Collectors.toList());
+                // 获取会员所属的重粉销售
+                List<FsUserCompanyUser> repeatCompanyUserNames = fsUserCompanyUserMapper.selectRepeatCompanyUserName(userIds);
+                Map<Long, String> map = repeatCompanyUserNames.stream().collect(Collectors.toMap(FsUserCompanyUser::getUserId, FsUserCompanyUser::getRepeatCompanyUserName));
 
-            for (FsUserPageListVO fsUserPageListVO : fsUserPageListVOS) {
-                fsUserPageListVO.setRepeatCompanyUserName(map.get(fsUserPageListVO.getUserId()));
-                if ("微信用户".equals(fsUserPageListVO.getNickname()) && StringUtils.isNotEmpty(fsUserPageListVO.getPhone())) {
-                    fsUserPageListVO.setNickname(fsUserPageListVO.getPhone());
-                }
-                if(StringUtils.isNotEmpty(fsUserPageListVO.getTag()) && fsUserPageListVO.getIsRepeatFans() == 0){
-                    StringBuilder newTag = removeRepeatFansTag(fsUserPageListVO);
-                    fsUserPageListVO.setTag(newTag.toString());
+                for (FsUserPageListVO fsUserPageListVO : fsUserPageListVOS) {
+                    fsUserPageListVO.setRepeatCompanyUserName(map.get(fsUserPageListVO.getUserId()));
+                    if ("微信用户".equals(fsUserPageListVO.getNickname()) && StringUtils.isNotEmpty(fsUserPageListVO.getPhone())) {
+                        fsUserPageListVO.setNickname(fsUserPageListVO.getPhone());
+                    }
+                    if(StringUtils.isNotEmpty(fsUserPageListVO.getTag()) && fsUserPageListVO.getIsRepeatFans() == 0){
+                        StringBuilder newTag = removeRepeatFansTag(fsUserPageListVO);
+                        fsUserPageListVO.setTag(newTag.toString());
+                    }
                 }
+                return new PageInfo<>(fsUserPageListVOS);
+            } else {
+                return new PageInfo<>(fsUserPageListVOS);
             }
-            return new PageInfo<>(fsUserPageListVOS);
-        } else {
-            return new PageInfo<>(fsUserPageListVOS);
+        }else {
+            return null;
         }
+
     }
 
     private static StringBuilder removeRepeatFansTag(FsUserPageListVO fsUserPageListVO) {
@@ -703,6 +727,8 @@ public class FsUserServiceImpl implements IFsUserService
         if (countRedPacket != null) {
             vo.setAnswerRedPacketTime(countRedPacket.getAnswerRedPacketTime());
             vo.setAnswerRedPacketAmount(countRedPacket.getAnswerRedPacketAmount());
+        } else {
+            vo.setAnswerRedPacketAmount(BigDecimal.ZERO);
         }
         if (countAnswer != null) {
             vo.setAnswerTime(countAnswer.getAnswerTime());
@@ -854,13 +880,18 @@ public class FsUserServiceImpl implements IFsUserService
             return ResponseResult.fail(404,"当前用户信息不存在");
         }
 
+        // 逻辑调整:如果会员已经绑定了销售,直接提示,不添加重粉数据了-2025年6月16日14点53分
+        if (fsUser.getCompanyUserId() != null && !param.getCompanyUserId().equals(fsUser.getCompanyUserId())){
+            return ResponseResult.fail(406,"该用户已成为其他销售会员");
+        }
+
         //判断该销售是否存在
         CompanyUser companyUser = companyUserMapper.selectCompanyUserById(param.getCompanyUserId());
         if (Objects.isNull(companyUser)){
             return ResponseResult.fail(405,"销售不存在");
         }
 
-        // 判断是否绑定了销售
+        // 添加关系表数据
         FsUserCompanyUser fsUserCompanyUser = getFsUserCompanyUser(param, fsUser);
         QueryWrapper<FsUserCompanyUser> queryWrapper = new QueryWrapper<FsUserCompanyUser>().eq("user_id", param.getUserId()).eq("company_user_id", param.getCompanyUserId());
         Integer i = fsUserCompanyUserMapper.selectCount(queryWrapper);
@@ -901,10 +932,10 @@ public class FsUserServiceImpl implements IFsUserService
             companyTagUserMapper.insertCompanyTagUser(companyTagUser);
         }
 
-        // 如果是重粉,直接打上重粉的标签
-        if(1 == fsUserCompanyUser.getIsRepeatFans()){
-            this.setRepeatFansTag(param);
-        }
+//        // 如果是重粉,直接打上重粉的标签
+//        if(1 == fsUserCompanyUser.getIsRepeatFans()){
+//            this.setRepeatFansTag(param);
+//        }
 
         //如果是设置了需要进入小黑屋,则需要返回提示,否则正常返回
         if(isDefaultBlack == 1){

+ 43 - 39
fs-service/src/main/java/com/fs/qw/service/impl/QwExternalContactServiceImpl.java

@@ -169,6 +169,9 @@ public class QwExternalContactServiceImpl extends ServiceImpl<QwExternalContactM
     @Autowired
     private SopUserLogsInfoMapper sopUserLogsInfoMapper;
 
+    @Autowired
+    private IQwCompanyService iQwCompanyService;
+
     @Autowired
     private ISopUserLogsService sopUserLogsService;
 
@@ -3114,9 +3117,7 @@ public class QwExternalContactServiceImpl extends ServiceImpl<QwExternalContactM
             return attachments;
         }
 
-        String json = configService.selectConfigByKey("course.config");
-        CourseConfig config = JSON.parseObject(json, CourseConfig.class);
-
+        QwCompany qwCompany = iQwCompanyService.getQwCompanyByRedis(corpId);
 
         attachments.forEach(att -> {
             // 生成短链的条件判断
@@ -3161,51 +3162,54 @@ public class QwExternalContactServiceImpl extends ServiceImpl<QwExternalContactM
 
                 try {
 
-                    String mediaId = (String) redisCache.getCacheObject("miniprogram:" + corpId + ":" + att.getMiniprogram().getCourseId());
-                    if (!StringUtil.strIsNullOrEmpty(mediaId)) {
-
-                        FsCourseLinkCreateParam param = new FsCourseLinkCreateParam();
-                        param.setVideoId(Long.valueOf(att.getMiniprogram().getVideoId()));
-                        param.setQwUserId(qwUser.getId());
-                        param.setDays(att.getMiniprogram().getExpiresDays());
-                        param.setCorpId(corpId);
-                        param.setCourseId(Long.valueOf(att.getMiniprogram().getCourseId()));
-                        param.setCompanyUserId(qwUser.getCompanyUserId());
-                        param.setCompanyId(qwUser.getCompanyId());
-                        param.setQwExternalId(qwExternalId);
-                        param.setSendTime(new Date());
+                    //小程序
+                    if("miniprogram".equals(att.getMsgtype())
+                            && !StringUtil.strIsNullOrEmpty(att.getMiniprogram().getCourseId())
+                            && !StringUtil.strIsNullOrEmpty(att.getMiniprogram().getVideoId())){
 
-                        String linkUrl = iFsCourseLinkService.createLinkUrlWcmini(param);
+                        try {
 
-                        if (!StringUtil.strIsNullOrEmpty(linkUrl)) {
-                            att.getMiniprogram().setPage(linkUrl);
-                        }
+                            String mediaId =(String)redisCache.getCacheObject("miniprogram:"+corpId+":"+att.getMiniprogram().getCourseId());
+                            if (!StringUtil.strIsNullOrEmpty(mediaId)){
 
-                        if (config!=null){
+                                FsCourseLinkCreateParam param = new FsCourseLinkCreateParam();
+                                param.setVideoId(Long.valueOf(att.getMiniprogram().getVideoId()));
+                                param.setQwUserId(qwUser.getId());
+                                param.setDays(att.getMiniprogram().getExpiresDays());
+                                param.setCorpId(corpId);
+                                param.setCourseId(Long.valueOf(att.getMiniprogram().getCourseId()));
+                                param.setCompanyUserId(qwUser.getCompanyUserId());
+                                param.setCompanyId(qwUser.getCompanyId());
+                                param.setQwExternalId(qwExternalId);
+                                param.setSendTime(new Date());
 
-                            if (StringUtil.strIsNullOrEmpty(config.getMiniprogramAppid())) {
-                                logger.error("配置中无小程序id,采用默认的");
-                                att.getMiniprogram().setAppid("wxc84c6f789ba7f176");
-                            } else {
+                                String linkUrl = iFsCourseLinkService.createLinkUrlWcmini(param);
 
-                                att.getMiniprogram().setAppid(config.getMiniprogramAppid());
+                                if (!StringUtil.strIsNullOrEmpty(linkUrl)) {
+                                    att.getMiniprogram().setPage(linkUrl);
+                                }
+                                if (!StringUtil.strIsNullOrEmpty(qwCompany.getMiniAppId())){
+                                    att.getMiniprogram().setAppid(qwCompany.getMiniAppId());
+                                }else {
+                                    logger.error("欢迎语:企业未配置小程序id:采用默认appid"+corpId);
+                                }
+                                att.getMiniprogram().setPic_media_id(mediaId);
+
+                                //生成观看记录
+                                addWatchLogIfNeeded(Integer.valueOf(att.getMiniprogram().getVideoId()),
+                                        Integer.valueOf(att.getMiniprogram().getCourseId()),
+                                        String.valueOf(qwUser.getId()),
+                                        String.valueOf(qwUser.getCompanyUserId()),
+                                        String.valueOf(qwUser.getCompanyId()),
+                                        String.valueOf(qwExternalId));
+                            }else {
+                                logger.error("查到课程相关信息:"+corpId+":"+att.getMiniprogram().getCourseId());
                             }
 
+                        }  catch (Exception e) {
+                            logger.error("欢迎语生成小程序消息失败:"+e.getMessage()+"|"+corpId+"|"+att.getMiniprogram().getCourseId());
                         }
-
-                        att.getMiniprogram().setPic_media_id(mediaId);
-
-                        //生成观看记录
-                        addWatchLogIfNeeded(Integer.valueOf(att.getMiniprogram().getVideoId()),
-                                Integer.valueOf(att.getMiniprogram().getCourseId()),
-                                String.valueOf(qwUser.getId()),
-                                String.valueOf(qwUser.getCompanyUserId()),
-                                String.valueOf(qwUser.getCompanyId()),
-                                String.valueOf(qwExternalId));
-                    }else {
-                        logger.error("查到课程相关信息:"+corpId+":"+att.getMiniprogram().getCourseId());
                     }
-
                 }  catch (Exception e) {
                     logger.error("欢迎语生成小程序消息失败:"+e.getMessage()+"|"+corpId+"|"+att.getMiniprogram().getCourseId());
                 }

+ 12 - 0
fs-service/src/main/java/com/fs/store/domain/FsUserCourseCount.java

@@ -80,6 +80,10 @@ public class FsUserCourseCount extends BaseEntity
     @Excel(name = "创建日期,为了创建唯一索引", width = 30, dateFormat = "yyyy-MM-dd")
     private Date createDate;
 
+    //最大的看课日期,用于查询唯一数据
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    private Date lastDate;
+
     public void setId(Long id)
     {
         this.id = id;
@@ -215,6 +219,14 @@ public class FsUserCourseCount extends BaseEntity
         this.createDate = createDate;
     }
 
+    public Date getLastDate() {
+        return lastDate;
+    }
+
+    public void setLastDate(Date lastDate) {
+        this.lastDate = lastDate;
+    }
+
     @Override
     public String toString() {
         return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)

+ 6 - 0
fs-service/src/main/java/com/fs/store/mapper/FsUserCourseCountMapper.java

@@ -69,6 +69,12 @@ public interface FsUserCourseCountMapper
      */
     List<FsUserCourseCount> getCountResult();
 
+    /**
+     * 获取最近七天每天最大心跳时间的看课记录数据
+     * @return
+     */
+    List<FsUserCourseCount> getUserStatusAndLastWatchDate();
+
     /**
      * 往看课统计表中插入数据
      */

+ 17 - 0
fs-service/src/main/java/com/fs/store/service/impl/FsUserCourseCountServiceImpl.java

@@ -13,6 +13,8 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
 import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
 
 /**
  * 用户看课统计Service业务层处理
@@ -116,6 +118,21 @@ public class FsUserCourseCountServiceImpl implements IFsUserCourseCountService
         // 1、获取统计结果
         List<FsUserCourseCount> countResult = fsUserCourseCountMapper.getCountResult();
 
+        // 查询用户-每天的最新的看课状态,和最后的心跳时间
+        List<FsUserCourseCount> userStatusAndLastWatchDate = fsUserCourseCountMapper.getUserStatusAndLastWatchDate();
+        Map<String, FsUserCourseCount> map = userStatusAndLastWatchDate.stream()
+                .collect(Collectors.toMap(k -> String.format("%s-%s", k.getUserId(), k.getLastDate()), v -> v));
+
+        for (FsUserCourseCount data : countResult) {
+            String key = String.format("%s-%s",data.getUserId(), data.getLastDate());
+            FsUserCourseCount fsUserCourseCount = map.get(key);
+            if(fsUserCourseCount != null){
+                data.setLastWatchDate(fsUserCourseCount.getLastWatchDate());
+                data.setStatus(fsUserCourseCount.getStatus());
+                data.setStopWatchDays(fsUserCourseCount.getStopWatchDays());
+            }
+        }
+
         // 2、分批插入数据
         this.batchInsert(countResult);
 

+ 3 - 1
fs-service/src/main/java/com/fs/store/vo/h5/UserDetailsVO.java

@@ -4,6 +4,8 @@ import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 
+import java.math.BigDecimal;
+
 /**
  * 用户会员详情 输出参数
  */
@@ -21,7 +23,7 @@ public class UserDetailsVO {
     private int answerRedPacketTime;
 
     @ApiModelProperty(value = "答题红包金额")
-    private int answerRedPacketAmount;
+    private BigDecimal answerRedPacketAmount;
 
     @ApiModelProperty(value = "完播次数")
     private int completeWatchCount;

+ 94 - 0
fs-service/src/main/resources/application-config-druid-bnkc.yml

@@ -0,0 +1,94 @@
+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: wx4115995705bb0ea0   #中康智慧
+        secret: 58910ae743005c396012b029c7def579
+        token: Ncbnd7lJvkripVOpyTFAna6NAWCxCrvC
+        aesKey: HlEiBB55eaWUaeBVAQO3cWKWPYv1vOVQSq7nFNICw4E
+        msgDataFormat: JSON
+      - appid: wxedde588767b358b1   #中康未来智慧药房
+        secret: 928d2961c81610d8f64b019597212fcd
+        token: Ncbnd7lJvkripVOpyTFAna6NAWCxCrvC
+        aesKey: HlEiBB55eaWUaeBVAQO3cWKWPYv1vOVQSq7nFNICw4E
+        msgDataFormat: JSON
+  cp:
+    corpId: wwb2a1055fb6c9a7c2
+    appConfigs:
+      - agentId: 1000005
+        secret: ec7okROXJqkNafq66-L6aKNv0asTzQIG0CYrj3vyBbo
+        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: wx5d3096e20e4bd8ba # 第一个公众号的appid  //公众号名称:成都九州在线互联网医院
+        secret: 1afa05f0c71beff0d52fb849c62e479a # 公众号的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
+nuonuo:
+  key: 10924508
+  secret: A2EB20764D304D16
+
+# 存储捅配置
+tencent_cloud_config:
+  secret_id: AKIDiMq9lDf2EOM9lIfqqfKo7FNgM5meD0sT
+  secret_key: u5SuS80342xzx8FRBukza9lVNHKNMSaB
+  bucket: bnkc-1323137866
+  app_id: 1323137866
+  region: ap-chongqing
+  proxy: bnkc
+tmp_secret_config:
+  secret_id: AKIDCj7NSNAovtqeJpBau8GZ4CGB71thXIxX
+  secret_key: lTB5zwqqz7CNhzDOWivFWedgfTBgxgBT
+  bucket: fs-1319721001
+  app_id: 1319721001
+  region: ap-chongqing
+  proxy: fs
+cloud_host:
+  company_name: 百年康成
+headerImg:
+  imgUrl: https
+ipad:
+  ipadUrl: http://ipad.cdwjyyh.com
+wx_miniapp_temp:
+  pay_order_temp_id:
+  inquiry_temp_id:
+
+

+ 2 - 9
fs-service/src/main/resources/application-config-druid-fcky.yml

@@ -46,7 +46,7 @@ watch:
   password3: v9xsKuqn_$d2y
 
 fs :
-  commonApi: http://127.0.0.1:7771
+  commonApi: http://10.206.0.16:8010
   h5CommonApi: http://127.0.0.1:7771
 nuonuo:
   key: 10924508
@@ -60,17 +60,10 @@ tencent_cloud_config:
   app_id: 1323137866
   region: ap-chongqing
   proxy: fcky
-tmp_secret_config:
-  secret_id: AKIDCj7NSNAovtqeJpBau8GZ4CGB71thXIxX
-  secret_key: lTB5zwqqz7CNhzDOWivFWedgfTBgxgBT
-  bucket: fs-1319721001
-  app_id: 1319721001
-  region: ap-chongqing
-  proxy: fs
 cloud_host:
   company_name: 蜂巢快药
 headerImg:
-  imgUrl: https
+  imgUrl: https://fc-1361520560.cos.ap-beijing.myqcloud.com/fs/20250619/ca569852d1da47f3bac8b209347c8011.png
 ipad:
   ipadUrl: http://ipad.cdwjyyh.com
 wx_miniapp_temp:

+ 2 - 2
fs-service/src/main/resources/application-config-druid-jzzx.yml

@@ -60,8 +60,8 @@ watch:
   password3: v9xsKuqn_$d2y
 
 fs :
-  commonApi: http://172.16.0.16:8010
-  h5CommonApi: http://119.29.195.254:8010
+  commonApi: http://127.0.0.1:8010
+  h5CommonApi: http://127.0.0.1:8010
 nuonuo:
   key: 10924508
   secret: A2EB20764D304D16

+ 79 - 0
fs-service/src/main/resources/application-config-druid-lmjy.yml

@@ -0,0 +1,79 @@
+baidu:
+  token:
+  back-domain:
+#配置
+logging:
+  level:
+    org.springframework.web: INFO
+    com.github.binarywang.demo.wx.cp: DEBUG
+    me.chanjar.weixin: DEBUG
+wx:
+  cp:
+    corpId: wwb2a1055fb6c9a7c2
+    appConfigs:
+      - agentId: 1000008
+        secret: ec7okROXJqkNafq66-L6aKNv0asTzQIG0CYrj3vyBbo
+        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: wx5d3096e20e4bd8bb # 第一个公众号的appid  //公众号名称:成都九州在线互联网医院
+        secret: 1afa05f0c71beff0d52fb849c62e479a # 公众号的appsecret
+        token: PPKOdAlCoMO # 接口配置里的Token值
+        aesKey: Eswa6VjwtVMCcw03qZy6fWllgrv5aytIA1SZPEU0kU2 # 接口配置里的EncodingAESKey值
+aifabu:  #爱链接
+  appKey:
+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://172.27.0.7:8010
+#  commonApi: http://127.0.0.1:8010
+  h5CommonApi: http://119.29.195.254:8010
+nuonuo:
+  key:
+  secret:
+
+
+  # 存储捅配置
+tencent_cloud_config:
+  secret_id: AKIDiMq9lDf2EOM9lIfqqfKo7FNgM5meD0sT
+  secret_key: u5SuS80342xzx8FRBukza9lVNHKNMSaB
+  bucket: lm-1323137866
+  app_id: 1323137866
+  region: ap-chongqing
+  proxy: lm
+cloud_host:
+  company_name: 良苗教育
+#看课授权时显示的头像
+headerImg:
+  imgUrl:
+ipad:
+  ipadUrl:
+
+wx_miniapp_temp:
+  pay_order_temp_id:
+  inquiry_temp_id:
+
+

+ 149 - 0
fs-service/src/main/resources/application-druid-bnkc.yml

@@ -0,0 +1,149 @@
+# 数据源配置
+spring:
+    profiles:
+        include: config-druid-bnkc,common
+    # redis 配置
+    redis:
+        host: 10.206.0.4
+        port: 6379
+        # 数据库索引
+        database: 0
+        # 密码
+        password: Ylrz_1q2w3e4r5t6y
+        # 连接超时时间
+        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://10.206.0.15:3306/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://10.206.0.15:3306/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
+

+ 150 - 0
fs-service/src/main/resources/application-druid-lmjy.yml

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

+ 2 - 2
fs-service/src/main/resources/application-druid-whhm.yml

@@ -5,7 +5,7 @@ spring:
     # redis 配置
     redis:
         # 地址
-        host: 10.206.0.14
+        host: 10.206.0.6
         # 端口,默认为6379
         port: 6379
         # 数据库索引
@@ -86,7 +86,7 @@ spring:
             druid:
                 # 主库数据源
                 master:
-                    url: jdbc:mysql://10.206.0.15:3306/sop?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
+                    url: jdbc:mysql://10.206.0.15:3306/fs_his_sop?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
                     username: root
                     password: Ylrz_1q2w3e4r5t6y
                 # 初始连接数

+ 13 - 4
fs-service/src/main/resources/mapper/company/CompanyUserMapper.xml

@@ -138,6 +138,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="voicePrintUrl != null">voice_print_url,</if>
             <if test="addressId != null">address_id,</if>
             <if test="domain != null">domain,</if>
+            <if test="isAudit != null">`is_audit`,</if>
         </trim>
         <trim prefix="values (" suffix=")" suffixOverrides=",">
             <if test="companyId != null">#{companyId},</if>
@@ -170,7 +171,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="voicePrintUrl != null">#{voicePrintUrl},</if>
             <if test="addressId != null">#{addressId},</if>
             <if test="domain != null">#{domain},</if>
-         </trim>
+            <if test="isAudit != null">#{isAudit},</if>
+        </trim>
     </insert>
 
     <update id="updateCompanyUser" parameterType="CompanyUser">
@@ -258,9 +260,15 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             *
         FROM
             company_user
-        WHERE
+        <where>
             del_flag = 0
-          AND (company_user.user_id = #{userId} or company_user.parent_id = #{userId})
+            <if test="companyId == null">
+                AND (company_user.user_id = #{userId} or company_user.parent_id = #{userId})
+            </if>
+            <if test="companyId != null">
+                AND company_user.company_id = #{companyId}
+            </if>
+        </where>
     </select>
     <select id="getAllUserListLimit" resultType="com.fs.company.domain.CompanyUser">
         SELECT * FROM company_user
@@ -299,8 +307,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 		    left join company_role r on r.role_id = ur.role_id
     </sql>
 
-    <select id="selectAllCompanyUserByDeptId" resultType="com.fs.company.domain.CompanyUser">
+    <select id="selectAllCompanyUserByCompanyIdAndDeptId" resultType="com.fs.company.domain.CompanyUser">
         select * from company_user where del_flag = '0'
+        and company_id = #{companyId}
         <if test="deptId != null">
             and dept_id = #{deptId}
         </if>

+ 7 - 1
fs-service/src/main/resources/mapper/course/FsCourseWatchLogMapper.xml

@@ -56,7 +56,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         select l.log_id,l.user_id,uc.course_name,v.title as video_name,qec.avatar as external_user_avatar,
         l.log_type,SEC_TO_TIME(l.duration) as duration,c.company_name,l.camp_period_time,l.finish_time,
         cu.nick_name as company_user_name ,l.send_type,l.create_time,l.update_time,l.last_heartbeat_time,
-        qu.qw_user_name,qec.name as external_user_name,c.company_id
+        qu.qw_user_name,qec.name as external_user_name,c.company_id,u.avatar as fsAvatar,u.nick_name as fsNickName
          from fs_course_watch_log l
          left join fs_user_course_video v on v.video_id = l.video_id
          left join fs_user_course uc on uc.course_id = l.course_id
@@ -66,6 +66,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
          LEFT JOIN qw_user qu on qu.id= l.qw_user_id
          LEFT JOIN qw_external_contact qec on l.qw_external_contact_id = qec.id
         <where>
+            <if test ='maps.sendType !=null'>
+                and l.send_type = #{maps.sendType}
+            </if>
             <if test ='maps.userId !=null'>
                 and l.user_id = #{maps.userId}
             </if>
@@ -208,6 +211,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="finishTime != null">finish_time,</if>
             <if test="sendFinishMsg != null">send_finish_msg,</if>
             <if test="campPeriodTime != null">camp_period_time,</if>
+            <if test="periodId != null">period_id,</if>
         </trim>
         <trim prefix="values (" suffix=")" suffixOverrides=",">
             <if test="userId != null">#{userId},</if>
@@ -227,6 +231,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="finishTime != null">#{finishTime},</if>
             <if test="sendFinishMsg != null">#{sendFinishMsg},</if>
             <if test="campPeriodTime != null">#{campPeriodTime},</if>
+            <if test="periodId != null">#{periodId},</if>
         </trim>
     </insert>
 
@@ -341,6 +346,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="finishTime != null">finish_time = #{finishTime},</if>
             <if test="sendFinishMsg != null">send_finish_msg = #{sendFinishMsg},</if>
             <if test="lastHeartbeatTime != null">last_heartbeat_time = #{lastHeartbeatTime},</if>
+            <if test="periodId != null">period_id = #{periodId},</if>
         </trim>
         where log_id = #{logId}
     </update>

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

@@ -114,6 +114,12 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             or fu.phone = #{params.keyword}
             )
         </if>
+        <if test="params.companyUserId != null">
+            and fcwl.company_user_id = #{params.companyUserId}
+        </if>
+        <if test="params.companyId != null">
+            and fcwl.company_id = #{params.companyId}
+        </if>
         <choose>
             <when test="params.type == 0">
                 and (

+ 7 - 0
fs-service/src/main/resources/mapper/his/FsPackageMapper.xml

@@ -69,6 +69,13 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         where package_id = #{packageId}
     </select>
 
+    <select id="selectIcdNameByPackageId" resultType="java.lang.String">
+        SELECT i.icd_name
+        FROM fs_package p
+                 LEFT JOIN fs_icd i ON FIND_IN_SET(i.icd_code, p.icd_code) > 0
+        WHERE package_id = #{packageId};
+    </select>
+
     <insert id="insertFsPackage" parameterType="FsPackage" useGeneratedKeys="true" keyProperty="packageId">
         insert into fs_package
         <trim prefix="(" suffix=")" suffixOverrides=",">

+ 28 - 24
fs-service/src/main/resources/mapper/his/FsUserMapper.xml

@@ -213,11 +213,14 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         LEFT JOIN fs_user_company_user ON fs_user_company_user.user_id = fs_user.user_id
         LEFT JOIN company_user ON company_user.user_id = fs_user_company_user.company_user_id
         where fs_user.is_del = 0
-        <if test="userId != null and userId !='' ">
-            and (company_user.user_id = #{userId} OR company_user.parent_id = #{userId} )
+        <if test="userId != null and userId!= 0 ">
+            and fs_user.company_user_id = #{userId}
         </if>
-        <if test="companyUserId != null and companyUserId !='' ">
-            and company_user.user_id = #{companyUserId}
+        <if test="companyId != null ">
+            and fs_user.company_id = #{companyId}
+        </if>
+        <if test="companyUserId != null and companyUserId!= '' ">
+            and fs_user.company_user_id = #{companyUserId}
         </if>
         <choose>
             <when test = "isBlack">
@@ -241,7 +244,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         <if test="tagIds != null and tagIds.length > 0">
             AND
             <foreach collection="tagIds" item="item" index="index" open="(" separator="or" close=")">
-                company_tag_user.tag_ids LIKE concat('%"',#{item},'"%')
+                CONCAT(',', company_tag_user.tag_ids, ',') LIKE CONCAT('%,', #{item}, ',%')
             </foreach>
         </if>
         <if test="tabValue != null and tabValue !='' ">
@@ -611,14 +614,14 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
                     <when test = "dateTag == '今天'">
                         and to_days(fs_user_course_count.create_time) = to_days(now())
                     </when>
-                    <when test = "dateTag == ' 昨天'">
-                        and to_days(now()) - to_days(fs_user_course_count.create_time) &lt;= 1
+                    <when test = "dateTag == '昨天'">
+                        and fs_user_course_count.create_time &gt;= CURDATE() - INTERVAL 1 DAY AND fs_user_course_count.create_time &lt; CURDATE()
                     </when>
                     <when test = "dateTag == '前天'">
-                        and to_days(now()) - to_days(fs_user_course_count.create_time) &lt;= 2
+                        and fs_user_course_count.create_time &gt;= CURDATE() - INTERVAL 2 DAY AND fs_user_course_count.create_time &lt; CURDATE() - INTERVAL 1 DAY
                     </when>
                     <when test = "dateTag == '近七天'">
-                        and DATE_SUB(CURDATE(), INTERVAL 7 DAY) &lt;= date(fs_user_course_count.create_time)
+                        and fs_user_course_count.create_time &gt;= CURDATE() - INTERVAL 7 DAY
                     </when>
                 </choose>
             </if>
@@ -639,20 +642,20 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         LEFT JOIN fs_user ON fs_user.user_id = fs_course_answer_logs.user_id
         LEFT JOIN company_user ON company_user.user_id = fs_user.company_user_id
         WHERE
-        company_user.parent_id = #{userId}
+        (company_user.user_id = #{userId} or company_user.parent_id = #{userId} )
         <if test="dateTag != null and dateTag !='' ">
             <choose>
                 <when test = "dateTag == '今天'">
                     and to_days(fs_course_answer_logs.create_time) = to_days(now())
                 </when>
-                <when test = "dateTag == ' 昨天'">
-                    and to_days(now()) - to_days(fs_course_answer_logs.create_time) &lt;= 1
+                <when test = "dateTag == '昨天'">
+                    and fs_course_answer_logs.create_time &gt;= CURDATE() - INTERVAL 1 DAY AND fs_course_answer_logs.create_time &lt; CURDATE()
                 </when>
                 <when test = "dateTag == '前天'">
-                    and to_days(now()) - to_days(fs_course_answer_logs.create_time) &lt;= 2
+                    and fs_course_answer_logs.create_time &gt;= CURDATE() - INTERVAL 2 DAY AND fs_course_answer_logs.create_time &lt; CURDATE() - INTERVAL 1 DAY
                 </when>
                 <when test = "dateTag == '近七天'">
-                    and DATE_SUB(CURDATE(), INTERVAL 7 DAY) &lt;= date(fs_course_answer_logs.create_time)
+                    and fs_course_answer_logs.create_time &gt;= CURDATE() - INTERVAL 7 DAY
                 </when>
             </choose>
         </if>
@@ -669,21 +672,21 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         LEFT JOIN fs_user ON fs_user.user_id = fs_course_answer_logs.user_id
         LEFT JOIN company_user ON company_user.user_id = fs_user.company_user_id
         WHERE
-        company_user.parent_id = #{userId}
+        (company_user.user_id = #{userId} or company_user.parent_id = #{userId} )
         AND fs_course_answer_logs.is_right = 1
         <if test="dateTag != null and dateTag !='' ">
             <choose>
                 <when test = "dateTag == '今天'">
                     and to_days(fs_course_answer_logs.create_time) = to_days(now())
                 </when>
-                <when test = "dateTag == ' 昨天'">
-                    and to_days(now()) - to_days(fs_course_answer_logs.create_time) &lt;= 1
+                <when test = "dateTag == '昨天'">
+                    and fs_course_answer_logs.create_time &gt;= CURDATE() - INTERVAL 1 DAY AND fs_course_answer_logs.create_time &lt; CURDATE()
                 </when>
                 <when test = "dateTag == '前天'">
-                    and to_days(now()) - to_days(fs_course_answer_logs.create_time) &lt;= 2
+                    and fs_course_answer_logs.create_time &gt;= CURDATE() - INTERVAL 2 DAY AND fs_course_answer_logs.create_time &lt; CURDATE() - INTERVAL 1 DAY
                 </when>
                 <when test = "dateTag == '近七天'">
-                    and DATE_SUB(CURDATE(), INTERVAL 7 DAY) &lt;= date(fs_course_answer_logs.create_time)
+                    and fs_course_answer_logs.create_time &gt;= CURDATE() - INTERVAL 7 DAY
                 </when>
             </choose>
         </if>
@@ -704,20 +707,21 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         LEFT JOIN fs_user ON fs_user.user_id = fs_course_red_packet_log.user_id
         LEFT JOIN company_user ON company_user.user_id = fs_user.company_user_id
         WHERE
-        company_user.parent_id = #{userId}
+        (company_user.user_id = #{userId} or company_user.parent_id = #{userId} )
+        and fs_course_red_packet_log.status = 1
         <if test="dateTag != null and dateTag !='' ">
             <choose>
                 <when test = "dateTag == '今天'">
                     and to_days(fs_course_red_packet_log.create_time) = to_days(now())
                 </when>
-                <when test = "dateTag == ' 昨天'">
-                    and to_days(now()) - to_days(fs_course_red_packet_log.create_time) &lt;= 1
+                <when test = "dateTag == '昨天'">
+                    and fs_course_red_packet_log.create_time &gt;= CURDATE() - INTERVAL 1 DAY AND fs_course_red_packet_log.create_time &lt; CURDATE()
                 </when>
                 <when test = "dateTag == '前天'">
-                    and to_days(now()) - to_days(fs_course_red_packet_log.create_time) &lt;= 2
+                    and fs_course_red_packet_log.create_time &gt;= CURDATE() - INTERVAL 2 DAY AND fs_course_red_packet_log.create_time &lt; CURDATE() - INTERVAL 1 DAY
                 </when>
                 <when test = "dateTag == '近七天'">
-                    and DATE_SUB(CURDATE(), INTERVAL 7 DAY) &lt;= date(fs_course_red_packet_log.create_time)
+                    and fs_course_red_packet_log.create_time &gt;= CURDATE() - INTERVAL 7 DAY
                 </when>
             </choose>
         </if>

+ 33 - 15
fs-service/src/main/resources/mapper/store/FsUserCourseCountMapper.xml

@@ -149,30 +149,48 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             ( count( DISTINCT CASE WHEN fwl.log_type = 3 THEN fwl.video_id END ) > 0, 1, 2 ) AS missCourseStatus,
             GROUP_CONCAT( DISTINCT fwl.period_id ) AS courseIds,
             count(DISTINCT fwl.period_id ) AS partCourseCount,
-            a.last_heartbeat_time AS lastWatchDate,
-            CASE
-                WHEN a.log_type = 1
-                    OR a.log_type = 2 THEN
-                    1
-                WHEN a.log_type = 4 THEN
-                    2
-                WHEN a.log_type = 3 THEN
-                    3
-                END AS STATUS,
-            DATEDIFF(DATE_FORMAT(NOW(),'%Y-%m-%d'),DATE_FORMAT(a.last_heartbeat_time,'%Y-%m-%d')) as stop_watch_days,
             max( CASE WHEN fwl.log_type = 2 THEN fwl.last_heartbeat_time END ) AS completeWatchDate,
             count( CASE WHEN fwl.log_type = 2 THEN fwl.log_id END ) AS completeWatchCount,
             count( CASE WHEN fwl.log_type != 3 THEN fwl.log_id END ) AS watch_times,
-            NOW() AS create_time,
+            DATE_FORMAT(fwl.create_time,'%Y-%m-%d 00:00:00') AS createTime,
             NOW() AS updateTime,
-            curdate() AS create_date
+            DATE_FORMAT(fwl.create_time,'%Y-%m-%d') AS create_date,
+            DATE (fwl.create_time ) AS lastDate
         FROM
-            ( SELECT fs_course_watch_log.user_id, Max( fs_course_watch_log.last_heartbeat_time ) AS last_heartbeat_time, log_type FROM fs_course_watch_log GROUP BY fs_course_watch_log.user_id ) a
-                INNER JOIN fs_course_watch_log fwl ON fwl.user_id = a.user_id
+            fs_course_watch_log fwl
+        where fwl.send_type = 1 and fwl.create_time &gt;= DATE_SUB(CURDATE(), INTERVAL 7 DAY)
         GROUP BY
             fwl.user_id
     </select>
 
+    <select id="getUserStatusAndLastWatchDate" resultType="FsUserCourseCount">
+        SELECT
+            fs_course_watch_log.user_id,
+            Max( fs_course_watch_log.last_heartbeat_time ) AS lastWatchDate,
+            Max( DATE ( fs_course_watch_log.create_time ) ) AS lastDate,
+            CASE
+
+                WHEN fs_course_watch_log.log_type = 1
+                    OR fs_course_watch_log.log_type = 2 THEN
+                    1
+                WHEN fs_course_watch_log.log_type = 4 THEN
+                    2
+                WHEN fs_course_watch_log.log_type = 3 THEN
+                    3
+                END AS STATUS,
+            DATEDIFF(
+                    DATE_FORMAT( NOW(), '%Y-%m-%d' ),
+                    DATE_FORMAT( fs_course_watch_log.last_heartbeat_time, '%Y-%m-%d' )) AS stop_watch_days
+        FROM
+            fs_course_watch_log
+        WHERE
+            fs_course_watch_log.send_type = 1
+          AND fs_course_watch_log.create_time >= DATE_SUB( CURDATE(), INTERVAL 7 DAY )
+        GROUP BY
+            fs_course_watch_log.user_id, date(fs_course_watch_log.create_time)
+    </select>
+
+
     <insert id="insertFsUserCourseCountTask" parameterType="FsUserCourseCount" useGeneratedKeys="true" keyProperty="id">
         insert into fs_user_course_count
         <trim prefix="(" suffix=")" suffixOverrides=",">

+ 6 - 0
fs-user-app/src/main/java/com/fs/app/controller/DoctorController.java

@@ -137,4 +137,10 @@ public class DoctorController extends  AppBaseController {
             return R.ok("已关注");
         }
     }
+
+    @ApiOperation("随机获取一个协定方医生")
+    @GetMapping("/getAgreement")
+    public R getAgreement(){
+        return R.ok().put("doctor",userDoctorService.getAgreement());
+    }
 }

+ 7 - 0
fs-user-app/src/main/java/com/fs/app/controller/PackageController.java

@@ -135,6 +135,13 @@ public class PackageController extends AppBaseController {
 //        return R.ok().put("data",fsPackage).put("storeName",storeName);
     }
 
+    @ApiOperation("获取ic名字")
+    @GetMapping("/getIcdNameByPackageId")
+    public R getIcdNameByPackageId(@RequestParam("packageId") Long packageId) {
+        List<String> icdNames = packageService.selectIcdNameByPackageId(packageId);
+        return R.ok().put("icdNames", icdNames);
+    }
+
     @ApiOperation("获取套餐下医生")
     @GetMapping("/getPackageDoctorList")
     public R getPackageDoctorList(FsDoctorListUParam param) {

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

@@ -0,0 +1,129 @@
+package com.fs.app.controller;
+
+import cn.hutool.core.date.DateTime;
+import com.fs.app.param.FsUserLoginByMpParam;
+import com.fs.app.utils.JwtUtils;
+import com.fs.common.core.domain.R;
+import com.fs.common.core.redis.RedisCache;
+import com.fs.company.domain.Company;
+import com.fs.company.domain.CompanyUser;
+import com.fs.company.service.ICompanyService;
+import com.fs.company.service.ICompanyUserService;
+import com.fs.course.mapper.FsCourseWatchLogMapper;
+import com.fs.qw.mapper.QwExternalContactMapper;
+import com.fs.his.domain.FsUser;
+import com.fs.his.service.IFsUserService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.extern.slf4j.Slf4j;
+import me.chanjar.weixin.common.bean.WxOAuth2UserInfo;
+import me.chanjar.weixin.common.bean.oauth2.WxOAuth2AccessToken;
+import me.chanjar.weixin.common.error.WxErrorException;
+import me.chanjar.weixin.mp.api.WxMpService;
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.validation.Valid;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+
+@Api("会员-h5-微信相关接口(后面不需要这个接口了,再删除))")
+@RestController
+@RequestMapping("/app/wx/h5/mp")
+@Slf4j
+public class WxH5MpController {
+    Logger logger = LoggerFactory.getLogger(getClass());
+    @Autowired
+    private WxMpService wxMpService;
+
+    @Autowired
+    private IFsUserService userService;
+
+    @Autowired
+    JwtUtils jwtUtils;
+    @Autowired
+    RedisCache redisCache;
+
+    @Autowired
+    FsCourseWatchLogMapper fsCourseWatchLogMapper;
+    @Autowired
+    QwExternalContactMapper qwExternalContactMapper;
+    @Autowired
+    ICompanyService companyService;
+    @Autowired
+    ICompanyUserService companyUserService;
+
+
+    @ApiOperation("课程分享链接公众号登录")
+    @PostMapping("/loginByMp")
+    public R loginByMp(@Valid @RequestBody FsUserLoginByMpParam param) throws WxErrorException {
+//        try {
+            //获取微信用户信息
+            WxOAuth2AccessToken wxMpOAuth2AccessToken = wxMpService.getOAuth2Service().getAccessToken(param.getCode());
+            WxOAuth2UserInfo wxMpUser = wxMpService.getOAuth2Service().getUserInfo(wxMpOAuth2AccessToken, null);
+            //1、特殊(需求设计:需要根据公司是否开启黑名单来设置会员初始化的状态)
+            Company company = null;
+            if(param.getCompanyId() != null){
+                company = companyService.selectCompanyById(param.getCompanyId());
+            }
+            // 根据销售后台设置的  是否需要单独注册会员 来判断是否需要设置销售的值
+            CompanyUser companyUser = companyUserService.selectCompanyUserById(param.getCompanyUserId());
+
+            FsUser user;
+            if(StringUtils.isNotEmpty(wxMpUser.getUnionId())) {
+                user = userService.selectFsUserByUnionId(wxMpUser.getUnionId());
+            } else {
+                user = userService.selectFsUserByMpOpenId(wxMpUser.getOpenid());
+            }
+            if (user != null) {
+                //修改
+                FsUser userMap = new FsUser();
+                userMap.setUserId(user.getUserId());
+                userMap.setMpOpenId(wxMpUser.getOpenid());
+                userMap.setUnionId(wxMpUser.getUnionId());
+                userMap.setUpdateTime(new DateTime());
+                userMap.setAvatar(wxMpUser.getHeadImgUrl());
+                userMap.setNickName(wxMpUser.getNickname());
+                userService.updateFsUser(userMap);
+            } else {
+                //新增
+                user = new FsUser();
+                user.setNickName(wxMpUser.getNickname());
+                user.setAvatar(wxMpUser.getHeadImgUrl());
+                user.setStatus((company != null ? company.getFsUserIsDefaultBlack() : 0) == 1 ? 0 : 1);
+                user.setMpOpenId(wxMpUser.getOpenid());
+                user.setUnionId(wxMpUser.getUnionId());
+                user.setCreateTime(new Date());
+                if(companyUser.getIsNeedRegisterMember() != 1){
+                    user.setCompanyId(param.getCompanyId());
+                    user.setCompanyUserId(param.getCompanyUserId());
+                }
+                userService.insertFsUser(user);
+            }
+            log.error("用户信息user: {}, 用户id: {}", user, user.getUserId());
+            String token = jwtUtils.generateToken(user.getUserId());
+            redisCache.setCacheObject("token:" + user.getUserId(), token, 604800, TimeUnit.SECONDS);
+            Map<String, Object> map = new HashMap<>();
+            map.put("token", token);
+            map.put("user", user);
+            return R.ok(map);
+//        } catch (WxErrorException e) {
+//            if (e.getError().getErrorCode() == 40163) {
+//                return R.error(40163, e.getError().getErrorMsg());
+//            } else {
+//                return R.error("授权失败," + e.getMessage());
+//            }
+//        }
+
+    }
+
+
+}

+ 10 - 0
fs-user-app/src/main/java/com/fs/app/param/FsUserLoginByMpParam.java

@@ -1,8 +1,10 @@
 package com.fs.app.param;
 
+import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 
 import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
 import java.io.Serializable;
 
 @Data
@@ -10,4 +12,12 @@ public class FsUserLoginByMpParam implements Serializable {
     @NotBlank(message = "code参数缺失")
     private String code;
     private Long videoId;
+
+    @NotNull(message = "公司id不能为空")
+    @ApiModelProperty(value = "公司id")
+    private Long companyId;
+
+    @NotNull(message = "销售id不能为空")
+    @ApiModelProperty(value = "销售id")
+    private Long companyUserId;
 }