Browse Source

Merge remote-tracking branch 'origin/master'

吴树波 2 tháng trước cách đây
mục cha
commit
950213ef80
35 tập tin đã thay đổi với 1077 bổ sung86 xóa
  1. 6 3
      fs-company-app/src/main/java/com/fs/app/controller/CompanyTagController.java
  2. 83 11
      fs-company-app/src/main/java/com/fs/app/controller/FsUserController.java
  3. 21 0
      fs-company-app/src/main/java/com/fs/app/controller/FsUserCourseVideoController.java
  4. 1 11
      fs-company-app/src/main/java/com/fs/app/exception/FSExceptionHandler.java
  5. 22 0
      fs-company-app/src/main/java/com/fs/app/param/FsUserTagUpdateParam.java
  6. 26 0
      fs-company-app/src/main/java/com/fs/app/param/FsUserUpdateParam.java
  7. 54 0
      fs-qwhook/src/main/java/com/fs/app/controller/AppBaseController.java
  8. 72 0
      fs-qwhook/src/main/java/com/fs/app/controller/FsUserCourseVideoController.java
  9. 7 0
      fs-service-system/src/main/java/com/fs/company/mapper/CompanyTagMapper.java
  10. 6 0
      fs-service-system/src/main/java/com/fs/company/mapper/CompanyTagUserMapper.java
  11. 9 0
      fs-service-system/src/main/java/com/fs/company/service/ICompanyTagUserService.java
  12. 39 3
      fs-service-system/src/main/java/com/fs/company/service/impl/CompanyTagUserServiceImpl.java
  13. 1 1
      fs-service-system/src/main/java/com/fs/course/mapper/FsCourseLinkMapper.java
  14. 8 0
      fs-service-system/src/main/java/com/fs/course/mapper/FsUserCourseMapper.java
  15. 4 0
      fs-service-system/src/main/java/com/fs/course/param/newfs/UserCourseVideoPageParam.java
  16. 7 0
      fs-service-system/src/main/java/com/fs/course/service/IFsUserCourseService.java
  17. 22 0
      fs-service-system/src/main/java/com/fs/course/service/impl/FsUserCourseServiceImpl.java
  18. 8 8
      fs-service-system/src/main/java/com/fs/course/service/impl/FsUserCourseVideoServiceImpl.java
  19. 66 0
      fs-service-system/src/main/java/com/fs/course/vo/FsUserCourseParticipationRecordVO.java
  20. 52 0
      fs-service-system/src/main/java/com/fs/course/vo/newfs/FsCourseAnalysisCountVO.java
  21. 43 0
      fs-service-system/src/main/java/com/fs/course/vo/newfs/FsCourseAnalysisVO.java
  22. 7 4
      fs-service-system/src/main/java/com/fs/sop/service/impl/SopUserLogsInfoServiceImpl.java
  23. 16 4
      fs-service-system/src/main/java/com/fs/store/mapper/FsUserMapper.java
  24. 37 0
      fs-service-system/src/main/java/com/fs/store/param/h5/CourseAnalysisParam.java
  25. 40 0
      fs-service-system/src/main/java/com/fs/store/param/h5/UserStatisticsCommonParam.java
  26. 25 17
      fs-service-system/src/main/java/com/fs/store/service/IFsUserService.java
  27. 79 11
      fs-service-system/src/main/java/com/fs/store/service/impl/FsUserServiceImpl.java
  28. 26 0
      fs-service-system/src/main/java/com/fs/store/vo/h5/CompanyUserSummaryCountVO.java
  29. 13 2
      fs-service-system/src/main/resources/mapper/company/CompanyTagMapper.xml
  30. 10 1
      fs-service-system/src/main/resources/mapper/company/CompanyTagUserMapper.xml
  31. 64 0
      fs-service-system/src/main/resources/mapper/course/FsUserCourseMapper.xml
  32. 1 3
      fs-service-system/src/main/resources/mapper/course/FsUserCourseVideoMapper.xml
  33. 164 4
      fs-service-system/src/main/resources/mapper/store/FsUserMapper.xml
  34. 20 3
      fs-user-app/src/main/java/com/fs/app/controller/CourseH5Controller.java
  35. 18 0
      fs-user-app/src/main/java/com/fs/app/controller/WxMpController.java

+ 6 - 3
fs-company-app/src/main/java/com/fs/app/controller/CompanyTagController.java

@@ -4,6 +4,7 @@ import com.alibaba.fastjson.JSON;
 import com.fs.app.annotation.Login;
 import com.fs.common.core.domain.R;
 import com.fs.common.exception.CustomException;
+import com.fs.common.utils.StringUtils;
 import com.fs.company.domain.CompanyTag;
 import com.fs.company.service.ICompanyTagService;
 import com.fs.company.service.ICompanyTagUserService;
@@ -42,8 +43,10 @@ public class CompanyTagController extends AppBaseController {
         log.debug("查询公司标签列表 keyword: {}, pageNum: {}, pageSize: {}", keyword, pageNum, pageSize);
 
         Map<String, Object> params = new HashMap<>();
-        params.put("keyword", keyword);
         params.put("companyId", getCompanyId());
+        if (StringUtils.isNotBlank(keyword)) {
+            params.put("keyword", keyword.split(","));
+        }
 
         PageHelper.startPage(pageNum, pageSize);
         List<CompanyTag> list = companyTagService.selectCompanyTagListByMap(params);
@@ -78,9 +81,9 @@ public class CompanyTagController extends AppBaseController {
     @Login
     @GetMapping("/tagSubUsers")
     @ApiOperation("标签下会员列表")
-    public R tagSubUsers(@RequestParam Long tagId) {
+    public R tagSubUsers(@RequestParam List<Long> tagId) {
         Map<String, Object> params = new HashMap<>();
-        params.put("tagId", tagId);
+        params.put("tagIds", tagId);
         params.put("companyId", getCompanyId());
         return R.ok().put("data", companyTagUserService.selectUserListByMap(params));
     }

+ 83 - 11
fs-company-app/src/main/java/com/fs/app/controller/FsUserController.java

@@ -1,16 +1,21 @@
 package com.fs.app.controller;
 
 
+import com.alibaba.fastjson.JSON;
 import com.fs.app.annotation.Login;
-import com.fs.app.utils.ValidateUtil;
-import com.fs.common.core.domain.R;
+import com.fs.app.param.FsUserTagUpdateParam;
+import com.fs.app.param.FsUserUpdateParam;
 import com.fs.common.core.domain.ResponseResult;
+import com.fs.common.exception.ServiceException;
 import com.fs.company.domain.CompanyUser;
 import com.fs.company.service.ICompanyTagUserService;
 import com.fs.company.service.ICompanyUserService;
-import com.fs.company.vo.CompanyQueryVo;
+import com.fs.course.vo.newfs.FsCourseAnalysisVO;
+import com.fs.store.param.h5.CourseAnalysisParam;
+import com.fs.store.domain.FsUser;
 import com.fs.store.param.h5.FsUserPageListParam;
 import com.fs.store.param.h5.TagListParam;
+import com.fs.store.param.h5.UserStatisticsCommonParam;
 import com.fs.store.service.IFsUserService;
 import com.fs.store.vo.h5.*;
 import com.github.pagehelper.PageHelper;
@@ -18,16 +23,18 @@ import com.github.pagehelper.PageInfo;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import io.swagger.annotations.ApiParam;
+import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
 
+import javax.validation.Valid;
 import java.text.SimpleDateFormat;
 import java.time.LocalDate;
 import java.util.Date;
 import java.util.List;
-import java.util.Map;
-
+import java.util.Objects;
 
+@Slf4j
 @Api(tags = "用户会员相关接口")
 @RestController
 @RequestMapping("/app/fs/user")
@@ -124,10 +131,14 @@ public class FsUserController extends AppBaseController {
         SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
         String nowDate = dateFormat.format(new Date());
         /*---------- 如果传入的日期是今天 ----------*/
-        FsUserStatisticsVO vo = fsUserService.userStatistics(userId, startTime, endTime, null, null);
+        UserStatisticsCommonParam param = new UserStatisticsCommonParam();
+        param.setUserId(userId).setStartTime(startTime).setEndTime(endTime);
+        FsUserStatisticsVO vo = fsUserService.userStatistics(param);
         if (nowDate.compareTo(startTime) > 0 && nowDate.compareTo(endTime) < 0) {
             String yesterday = LocalDate.now().minusDays(1).toString();
-            FsUserStatisticsVO fsUserStatisticsVO = fsUserService.userStatistics(userId, yesterday + " 00:00:00", yesterday + " 23:59:59", null, null);
+            UserStatisticsCommonParam paramYes = new UserStatisticsCommonParam();
+            paramYes.setUserId(userId).setStartTime(yesterday + " 00:00:00").setEndTime(yesterday + " 23:59:59");
+            FsUserStatisticsVO fsUserStatisticsVO = fsUserService.userStatistics(paramYes);
             vo.setYesterdayVO(fsUserStatisticsVO);
         }
         return ResponseResult.ok(vo);
@@ -139,7 +150,9 @@ public class FsUserController extends AppBaseController {
                                                                     @ApiParam(value = "视频id") @RequestParam(required = false) String videoId) {
         long userId = Long.parseLong(getUserId());
         long companyId = getCompanyId();
-        FsUserStatisticsVO fsUserStatisticsVO = fsUserService.userStatisticsDetails(userId, courseId, videoId, companyId);
+        UserStatisticsCommonParam param = new UserStatisticsCommonParam();
+        param.setUserId(userId).setCourseId(courseId).setVideoId(videoId).setCompanyId(companyId);
+        FsUserStatisticsVO fsUserStatisticsVO = fsUserService.userStatisticsDetails(param);
         return ResponseResult.ok(fsUserStatisticsVO);
     }
 
@@ -174,9 +187,11 @@ public class FsUserController extends AppBaseController {
     @GetMapping("/firstPage/graphic")
     @ApiOperation("首页数据-转化漏斗图")
     public ResponseResult<List<FsUserGraphicStatisticsVO>> graphicStatistics(@ApiParam(value = "开始时间", required = true) @RequestParam String startTime,
-                                                                @ApiParam(value = "结束时间", required = true) @RequestParam String endTime) {
+                                                                             @ApiParam(value = "结束时间", required = true) @RequestParam String endTime) {
         long userId = Long.parseLong(getUserId());
-        List<FsUserGraphicStatisticsVO> list = fsUserService.graphicStatistics(userId, startTime, endTime, null, null);
+        UserStatisticsCommonParam param = new UserStatisticsCommonParam();
+        param.setUserId(userId).setStartTime(startTime).setEndTime(endTime);
+        List<FsUserGraphicStatisticsVO> list = fsUserService.graphicStatistics(param);
         return ResponseResult.ok(list);
     }
 
@@ -185,8 +200,65 @@ public class FsUserController extends AppBaseController {
     public ResponseResult<List<FsUserGraphicStatisticsVO>> graphicStatisticsDetails(@ApiParam(value = "课程id") @RequestParam(required = false) String courseId,
                                                                                     @ApiParam(value = "视频id") @RequestParam(required = false) String videoId) {
         long userId = Long.parseLong(getUserId());
-        List<FsUserGraphicStatisticsVO> list = fsUserService.graphicStatistics(userId, null, null, courseId, videoId);
+        UserStatisticsCommonParam param = new UserStatisticsCommonParam();
+        param.setUserId(userId).setCourseId(courseId).setVideoId(videoId);
+        List<FsUserGraphicStatisticsVO> list = fsUserService.graphicStatistics(param);
         return ResponseResult.ok(list);
     }
 
+    @Login
+    @ApiOperation("修改用户备注、姓名")
+    @PostMapping("/changeUserInfo")
+    public ResponseResult<Object> changeUserInfo(@Valid @RequestBody FsUserUpdateParam param) {
+        log.debug("修改用户备注、姓名 param:{}", JSON.toJSONString(param));
+        FsUser fsUser = fsUserService.selectFsUserById(param.getFsUserId());
+        if (Objects.isNull(fsUser)) {
+            throw new ServiceException("用户不存在");
+        }
+
+        fsUser.setNickname(param.getNickName());
+        fsUser.setRemark(param.getRemark());
+        fsUserService.updateFsUser(fsUser);
+        return ResponseResult.ok();
+    }
+
+    @Login
+    @ApiOperation("修改用户标签")
+    @PostMapping("/changeUserTags")
+    public ResponseResult<Object> changeUserTags(@Valid @RequestBody FsUserTagUpdateParam param) {
+        companyTagUserService.changeUserTags(param.getFsUserId(), param.getTagIds());
+        return ResponseResult.ok();
+    }
+
+    @GetMapping("/courseAnalysis")
+    @ApiOperation("管理-课程分析-分页列表查询")
+    public ResponseResult<PageInfo<FsCourseAnalysisVO>> courseAnalysisList(CourseAnalysisParam param) {
+        param.setCompanyId(getCompanyId());
+        PageHelper.startPage(param.getPageNum(), param.getPageSize());
+        List<FsCourseAnalysisVO> list = fsUserService.courseAnalysis(param);
+        PageInfo<FsCourseAnalysisVO> pageInfo = new PageInfo<>(list);
+        return ResponseResult.ok(pageInfo);
+    }
+
+    @GetMapping("/companyUser/details")
+    @ApiOperation("管理-群管数据-根据销售id,群管数据统计")
+    public ResponseResult<FsUserStatisticsVO> companyUserStatistics(@ApiParam(value = "课程id") @RequestParam(required = false) String courseId,
+                                                                    @ApiParam(value = "视频id") @RequestParam(required = false) String videoId,
+                                                                    @ApiParam(value = "销售用户id", required = true) @RequestParam String companyUserId) {
+        UserStatisticsCommonParam param = new UserStatisticsCommonParam();
+        param.setUserId(Long.parseLong(getUserId()))
+                .setCourseId(courseId).setVideoId(videoId)
+                .setCompanyId(getCompanyId())
+                .setCompanyUserId(companyUserId);
+        FsUserStatisticsVO fsUserStatisticsVO = fsUserService.userStatisticsDetails(param);
+        return ResponseResult.ok(fsUserStatisticsVO);
+    }
+
+    @GetMapping("/companyUser/summaryCount")
+    @ApiOperation("管理-群管数据-顶部会员统计")
+    public ResponseResult<CompanyUserSummaryCountVO> companyUserSummaryCount(@ApiParam(value = "销售用户id", required = true) @RequestParam String companyUserId) {
+        long userId = Long.parseLong(getUserId());
+        return ResponseResult.ok(fsUserService.companyUserSummaryCount(userId, companyUserId));
+    }
+
 }

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

@@ -1,11 +1,13 @@
 package com.fs.app.controller;
 
+import com.fs.app.annotation.Login;
 import com.fs.common.core.domain.R;
 import com.fs.common.core.domain.ResponseResult;
 import com.fs.course.param.newfs.FsUserCourseListParam;
 import com.fs.course.param.newfs.UserCourseVideoPageParam;
 import com.fs.course.service.IFsUserCourseService;
 import com.fs.course.service.IFsUserCourseVideoService;
+import com.fs.course.vo.FsUserCourseParticipationRecordVO;
 import com.fs.course.vo.newfs.FsUserCourseListVO;
 import com.fs.course.vo.newfs.FsUserCourseVideoDetailsVO;
 import com.fs.course.vo.newfs.FsUserCourseVideoPageListVO;
@@ -70,4 +72,23 @@ public class FsUserCourseVideoController extends AppBaseController {
         PageInfo<FsUserVideoListVO> result = new PageInfo<>(listCourseVideo);
         return ResponseResult.ok(result);
     }
+
+    @Login
+    @ApiOperation("参与记录")
+    @GetMapping("/participationRecord")
+    public ResponseResult<Object> participationRecord(@RequestParam Long courseId,
+                                                      @RequestParam Integer type,
+                                                      @RequestParam(required = false) String keyword,
+                                                      @RequestParam(required = false, defaultValue = "1") Integer pageNum,
+                                                      @RequestParam(required = false, defaultValue = "10") Integer pageSize) {
+        log.debug("参与记录 keyword: {}, pageNum: {}, pageSize: {}", keyword, pageNum, pageSize);
+        Map<String, Object> params = new HashMap<>();
+        params.put("courseId", courseId);
+        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 - 11
fs-company-app/src/main/java/com/fs/app/exception/FSExceptionHandler.java

@@ -54,17 +54,7 @@ public class FSExceptionHandler {
 	@ExceptionHandler(Exception.class)
 	public R handleException(Exception e){
 		logger.error(e.getMessage(), e);
-		if (e instanceof BindException){
-			BindException ex = (BindException)e;
-			List<ObjectError> allErrors = ex.getAllErrors();//捕获的所有错误对象
-			ObjectError error = allErrors.get(0);
-			String defaultMessage = error.getDefaultMessage();//异常内容
-
-			return R.error(defaultMessage);
-		}else {
-			return R.error(e.getMessage());
-		}
-
+		return R.error("系统异常");
 	}
 	@ExceptionHandler(BindException.class)
 	public R bindExceptionHandler(BindException e) {

+ 22 - 0
fs-company-app/src/main/java/com/fs/app/param/FsUserTagUpdateParam.java

@@ -0,0 +1,22 @@
+package com.fs.app.param;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.validation.constraints.NotNull;
+import java.util.List;
+
+@Data
+public class FsUserTagUpdateParam {
+    /**
+     * 用户ID
+     */
+    @ApiModelProperty("用户ID")
+    @NotNull(message = "用户ID不能为空")
+    private Long fsUserId;
+    /**
+     * 标签ID
+     */
+    @ApiModelProperty("标签ID集合")
+    private List<Long> tagIds;
+}

+ 26 - 0
fs-company-app/src/main/java/com/fs/app/param/FsUserUpdateParam.java

@@ -0,0 +1,26 @@
+package com.fs.app.param;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.validation.constraints.NotNull;
+
+@Data
+public class FsUserUpdateParam {
+    /**
+     * 用户ID
+     */
+    @ApiModelProperty("用户ID")
+    @NotNull(message = "用户ID不能为空")
+    private Long fsUserId;
+    /**
+     * 用户昵称
+     */
+    @ApiModelProperty("用户昵称")
+    private String nickName;
+    /**
+     * 用户备注
+     */
+    @ApiModelProperty("用户备注")
+    private String remark;
+}

+ 54 - 0
fs-qwhook/src/main/java/com/fs/app/controller/AppBaseController.java

@@ -0,0 +1,54 @@
+package com.fs.app.controller;
+
+
+import com.fs.app.exception.FSException;
+import com.fs.app.utils.JwtUtils;
+import com.fs.common.core.redis.RedisCache;
+import com.fs.common.utils.ServletUtils;
+import com.fs.company.domain.CompanyUser;
+import com.fs.company.service.ICompanyUserService;
+import com.fs.store.domain.FsUser;
+import com.fs.store.service.IFsUserService;
+import io.jsonwebtoken.Claims;
+import org.springframework.beans.factory.annotation.Autowired;
+
+
+public class AppBaseController {
+	@Autowired
+	JwtUtils jwtUtils;
+	@Autowired
+	RedisCache redisCache;
+
+	@Autowired
+	private ICompanyUserService companyUserService;
+	@Autowired
+	private IFsUserService userService;
+	public Long getCompanyId() {
+		String headValue =  ServletUtils.getRequest().getHeader("APPToken");
+		Claims claims=jwtUtils.getClaimByToken(headValue);
+		String userId = claims.getSubject().toString();
+		Long companyId =(Long)redisCache.getCacheObject("companyId:"+userId);
+		return companyId;
+	}
+	public String getUserId()
+	{
+		String headValue =  ServletUtils.getRequest().getHeader("APPToken");
+		Claims claims=jwtUtils.getClaimByToken(headValue);
+		String userId = claims.getSubject().toString();
+		return userId;
+	}
+	//获取商城手机号
+	public Long getUserId(Long companyUserId)
+	{
+		CompanyUser companyUser=companyUserService.selectCompanyUserById(companyUserId);
+		FsUser user=userService.selectFsUserByPhone(companyUser.getPhonenumber());
+		if(user==null){
+			throw new FSException("未授权,请用员工手机号登录商城");
+		}
+		return user.getUserId();
+	}
+
+
+
+
+}

+ 72 - 0
fs-qwhook/src/main/java/com/fs/app/controller/FsUserCourseVideoController.java

@@ -0,0 +1,72 @@
+package com.fs.app.controller;
+
+import com.fs.common.core.domain.ResponseResult;
+import com.fs.course.param.newfs.FsUserCourseListParam;
+import com.fs.course.param.newfs.UserCourseVideoPageParam;
+import com.fs.course.service.IFsUserCourseService;
+import com.fs.course.service.IFsUserCourseVideoService;
+import com.fs.course.vo.newfs.FsUserCourseListVO;
+import com.fs.course.vo.newfs.FsUserCourseVideoDetailsVO;
+import com.fs.course.vo.newfs.FsUserCourseVideoPageListVO;
+import com.fs.course.vo.newfs.FsUserVideoListVO;
+import com.github.pagehelper.PageHelper;
+import com.github.pagehelper.PageInfo;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.List;
+
+
+@Api("课程库相关接口")
+@RestController
+@RequestMapping("/app/fs/course")
+@Slf4j
+public class FsUserCourseVideoController extends AppBaseController {
+
+    @Autowired
+    private IFsUserCourseVideoService fsUserCourseVideoService;
+
+    @Autowired
+    private IFsUserCourseService fsUserCourseService;
+
+    @GetMapping("/pageList")
+    @ApiOperation("课程分页列表")
+    public ResponseResult<PageInfo<FsUserCourseVideoPageListVO>> list(UserCourseVideoPageParam param) {
+        PageHelper.startPage(param.getPageNum(), param.getPageSize());
+        param.setCompanyId(getCompanyId());
+        List<FsUserCourseVideoPageListVO> list = fsUserCourseVideoService.pageListCourseVideo(param);
+        PageInfo<FsUserCourseVideoPageListVO> pageInfo = new PageInfo<>(list);
+        return ResponseResult.ok(pageInfo);
+    }
+
+    @ApiOperation("课程视频详情")
+    @GetMapping(value = "/videoDetails")
+    public ResponseResult<FsUserCourseVideoDetailsVO> getVideoDetails(Long videoId) {
+        return fsUserCourseVideoService.getVideoDetails(videoId);
+    }
+
+    @GetMapping("/courseList")
+    @ApiOperation("获取课程下拉列表")
+    public ResponseResult<PageInfo<FsUserCourseListVO>> getAllCourseList(FsUserCourseListParam param) {
+        PageHelper.startPage(param.getPageNum(), param.getPageSize());
+        param.setCompanyId(getCompanyId());
+        List<FsUserCourseListVO> fsUserCourseList = fsUserCourseService.getFsUserCourseList(param);
+        PageInfo<FsUserCourseListVO> pageInfo = new PageInfo<>(fsUserCourseList);
+        return ResponseResult.ok(pageInfo);
+    }
+
+    @GetMapping("/videoList")
+    @ApiOperation("获取视频下拉列表")
+    public ResponseResult<PageInfo<FsUserVideoListVO>> getAllVideoList(UserCourseVideoPageParam param) {
+        PageHelper.startPage(param.getPageNum(), param.getPageSize());
+        param.setCompanyId(getCompanyId());
+        List<FsUserVideoListVO> listCourseVideo = fsUserCourseVideoService.getListCourseVideo(param);
+        PageInfo<FsUserVideoListVO> result = new PageInfo<>(listCourseVideo);
+        return ResponseResult.ok(result);
+    }
+}

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

@@ -68,4 +68,11 @@ public interface CompanyTagMapper
      * @return list
      */
     List<CompanyTag> selectCompanyTagListByMap(@Param("params") Map<String, Object> params);
+
+    /**
+     * 查询用户标签列表
+     * @param userId    用户ID
+     * @return  list
+     */
+    List<CompanyTag> selectCompanyTagListByUserId(@Param("userId") Long userId);
 }

+ 6 - 0
fs-service-system/src/main/java/com/fs/company/mapper/CompanyTagUserMapper.java

@@ -73,4 +73,10 @@ public interface CompanyTagUserMapper
      * @return  list
      */
     List<CompanyTagUserVO> selectUserListByMap(@Param("params") Map<String, Object> params);
+
+    /**
+     * 删除用户标签
+     * @param params    条件
+     */
+    void deleteCompanyTagUserByMap(@Param("params") Map<String, Object> params);
 }

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

@@ -8,6 +8,8 @@ import com.fs.company.vo.CompanyTagUserVO;
 import com.fs.store.param.h5.TagListParam;
 import com.fs.store.vo.h5.CompanyUserTagListVO;
 
+import javax.validation.constraints.NotNull;
+
 /**
  * companyService接口
  *
@@ -77,4 +79,11 @@ public interface ICompanyTagUserService
      * @return  list
      */
     List<CompanyTagUserVO> selectUserListByMap(Map<String, Object> params);
+
+    /**
+     * 修改用户标签
+     * @param fsUserId 用户ID
+     * @param tagIds   标签ID集合
+     */
+    void changeUserTags(Long fsUserId, List<Long> tagIds);
 }

+ 39 - 3
fs-service-system/src/main/java/com/fs/company/service/impl/CompanyTagUserServiceImpl.java

@@ -1,15 +1,16 @@
 package com.fs.company.service.impl;
 
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 import java.util.stream.Collectors;
 
+import com.fs.common.exception.ServiceException;
 import com.fs.common.utils.DateUtils;
 import com.fs.common.utils.StringUtils;
 import com.fs.company.domain.CompanyUser;
 import com.fs.company.mapper.CompanyUserMapper;
 import com.fs.company.vo.CompanyTagUserVO;
+import com.fs.store.domain.FsUser;
+import com.fs.store.mapper.FsUserMapper;
 import com.fs.store.param.h5.TagListParam;
 import com.fs.store.vo.h5.CompanyUserTagListVO;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -17,6 +18,7 @@ import org.springframework.stereotype.Service;
 import com.fs.company.mapper.CompanyTagUserMapper;
 import com.fs.company.domain.CompanyTagUser;
 import com.fs.company.service.ICompanyTagUserService;
+import org.springframework.transaction.annotation.Transactional;
 
 /**
  * companyService业务层处理
@@ -32,6 +34,8 @@ public class CompanyTagUserServiceImpl implements ICompanyTagUserService
 
     @Autowired
     private CompanyUserMapper  companyUserMapper;
+    @Autowired
+    private FsUserMapper fsUserMapper;
 
     /**
      * 查询company
@@ -133,4 +137,36 @@ public class CompanyTagUserServiceImpl implements ICompanyTagUserService
     public List<CompanyTagUserVO> selectUserListByMap(Map<String, Object> params) {
         return companyTagUserMapper.selectUserListByMap(params);
     }
+
+    /**
+     * 修改用户标签
+     * @param fsUserId 用户ID
+     * @param tagIds   标签ID集合
+     */
+    @Transactional(rollbackFor = Exception.class)
+    @Override
+    public void changeUserTags(Long fsUserId, List<Long> tagIds) {
+        FsUser fsUser = fsUserMapper.selectFsUserById(fsUserId);
+        if (Objects.isNull(fsUser)) {
+            throw new ServiceException("用户不存在");
+        }
+
+        // 删除原标签
+        Map<String, Object> params = new HashMap<>();
+        params.put("userId", fsUserId);
+        params.put("companyId", fsUser.getCompanyId());
+        params.put("companyUserId", fsUser.getCompanyUserId());
+        companyTagUserMapper.deleteCompanyTagUserByMap(params);
+
+        // 不为空则添加新标签
+        if (Objects.nonNull(tagIds) && !tagIds.isEmpty()) {
+            CompanyTagUser companyTagUser = new CompanyTagUser();
+            companyTagUser.setUserId(fsUserId);
+            companyTagUser.setCompanyId(fsUser.getCompanyId());
+            companyTagUser.setCompanyUserId(fsUser.getCompanyUserId());
+            companyTagUser.setTagIds(tagIds.stream().map(String::valueOf).collect(Collectors.joining(",")));
+            companyTagUser.setCreateTime(new Date());
+            companyTagUserMapper.insertCompanyTagUser(companyTagUser);
+        }
+    }
 }

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

@@ -62,7 +62,7 @@ public interface FsCourseLinkMapper
      */
     public int deleteFsCourseLinkByLinkIds(Long[] linkIds);
 
-    @Select("select link, real_link, update_time from fs_course_link where link = #{suffix} order by link_id desc limit 1 ")
+    @Select("select link, real_link, update_time,company_user_id from fs_course_link where link = #{suffix} order by link_id desc limit 1 ")
     FsCourseLink selectFsCourseLinkByLink(@Param("suffix") String suffix);
 
     void insertFsCourseLinkBatch(@Param("courseLinks")List<FsCourseLink> courseLinkToInsert);

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

@@ -1,6 +1,8 @@
 package com.fs.course.mapper;
 
 import java.util.List;
+import java.util.Map;
+
 import com.fs.course.domain.FsUserCourse;
 import com.fs.course.param.FsUserCourseAddStudyCourseParam;
 import com.fs.course.param.FsUserCourseListUParam;
@@ -231,4 +233,10 @@ public interface FsUserCourseMapper
 
     List<FsUserCourseListVO> getFsUserCourseList(FsUserCourseListParam param);
 
+    /**
+     * 查询用户参与记录
+     * @param params 条件
+     * @return  list
+     */
+    List<FsUserCourseParticipationRecordVO> getParticipationRecordByMap(@Param("params") Map<String, Object> params);
 }

+ 4 - 0
fs-service-system/src/main/java/com/fs/course/param/newfs/UserCourseVideoPageParam.java

@@ -26,6 +26,10 @@ public class UserCourseVideoPageParam implements Serializable {
     @ApiModelProperty(value = "公司id")
     private Long companyId;
 
+    private String corpId;
+
+    private String qwUserid;
+
 
 
 //    @ApiModelProperty(value = "视频状态 1:草稿,2:待审核,3:发布")

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

@@ -111,4 +111,11 @@ public interface IFsUserCourseService
      * @return
      */
     List<FsUserCourseListVO> getFsUserCourseList(FsUserCourseListParam param);
+
+    /**
+     * 查询用户参与记录
+     * @param params 条件
+     * @return  list
+     */
+    List<FsUserCourseParticipationRecordVO> getParticipationRecordByMap(Map<String, Object> params);
 }

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

@@ -5,6 +5,11 @@ import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
 import com.fs.common.core.domain.R;
 import com.fs.common.utils.DateUtils;
 import com.fs.common.utils.DictUtils;
+import com.fs.common.utils.StringUtils;
+import com.fs.company.domain.CompanyTag;
+import com.fs.company.domain.CompanyTagUser;
+import com.fs.company.mapper.CompanyTagMapper;
+import com.fs.company.mapper.CompanyTagUserMapper;
 import com.fs.course.domain.FsUserCourse;
 import com.fs.course.domain.FsUserCourseStudy;
 import com.fs.course.domain.FsUserCourseStudyLog;
@@ -46,6 +51,8 @@ public class FsUserCourseServiceImpl implements IFsUserCourseService
     private FsUserCourseStudyMapper fsUserCourseStudyMapper;
     @Autowired
     private FsUserCourseStudyLogMapper fsUserCourseStudyLogMapper;
+    @Autowired
+    private CompanyTagMapper companyTagMapper;
 
     /**
      * 查询课程
@@ -368,4 +375,19 @@ public class FsUserCourseServiceImpl implements IFsUserCourseService
     public List<FsUserCourseListVO> getFsUserCourseList(FsUserCourseListParam param) {
         return fsUserCourseMapper.getFsUserCourseList(param);
     }
+
+    /**
+     * 查询用户参与记录
+     * @param params 条件
+     * @return  list
+     */
+    @Override
+    public List<FsUserCourseParticipationRecordVO> getParticipationRecordByMap(Map<String, Object> params) {
+        List<FsUserCourseParticipationRecordVO> list = fsUserCourseMapper.getParticipationRecordByMap(params);
+        list.forEach(recordVO -> {
+            List<CompanyTag> companyTags = companyTagMapper.selectCompanyTagListByUserId(recordVO.getUserId());
+            recordVO.setTags(companyTags);
+        });
+        return list;
+    }
 }

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

@@ -530,12 +530,12 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
             if (StringUtils.isNotEmpty(trafficLog.getUuId())) {
                 // 直接插入或更新
 //                logger.error("zyp \n【插入或更新流量】:{}",trafficLog);
-                if(ObjectUtils.isNotNull(trafficLog.getCourseId())) {
-                    FsUserCourse course = fsUserCourseCacheService.selectFsUserCourseByCourseId(trafficLog.getCourseId());
-                    if(ObjectUtils.isNotNull(course)){
-                        trafficLog.setProject(course.getProject());
-                    }
-                }
+//                if(ObjectUtils.isNotNull(trafficLog.getCourseId())) {
+//                    FsUserCourse course = fsUserCourseCacheService.selectFsUserCourseByCourseId(trafficLog.getCourseId());
+//                    if(ObjectUtils.isNotNull(course)){
+//                        trafficLog.setProject(course.getProject());
+//                    }
+//                }
                 fsCourseTrafficLogMapper.insertOrUpdateTrafficLog(trafficLog);
             }
         } catch (Exception e) {
@@ -703,7 +703,7 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
             }
             // 添加红包记录
             redPacketLog.setCourseId(param.getCourseId());
-            redPacketLog.setOutBatchNo(sendRedPacket.get("orderCode").toString());
+//            redPacketLog.setOutBatchNo(sendRedPacket.get("orderCode").toString());
             redPacketLog.setCompanyId(param.getCompanyId());
             redPacketLog.setUserId(param.getUserId());
             redPacketLog.setVideoId(param.getVideoId());
@@ -720,7 +720,7 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
                 log.setRewardType(config.getRewardType());
                 courseWatchLogMapper.updateFsCourseWatchLog(log);
             }
-            return R.ok("奖励发放成功");
+            return sendRedPacket;
         } else {
             return R.error("奖励发送失败,请联系客服");
         }

+ 66 - 0
fs-service-system/src/main/java/com/fs/course/vo/FsUserCourseParticipationRecordVO.java

@@ -0,0 +1,66 @@
+package com.fs.course.vo;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fs.company.domain.CompanyTag;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+import java.util.List;
+
+@Data
+public class FsUserCourseParticipationRecordVO {
+    /**
+     * 用户ID
+     */
+    private Long userId;
+    /**
+     * 课程ID
+     */
+    private Long courseId;
+    /**
+     * 用户昵称
+     */
+    private String nickName;
+    /**
+     * 用户名称
+     */
+    private String userName;
+    /**
+     * 头像
+     */
+    private String avatar;
+    /**
+     * 用户电话号码
+     */
+    private String phoneNumber;
+    /**
+     * 注册时间
+     */
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    private LocalDateTime createTime;
+    /**
+     * 观看次数
+     */
+    private Integer watchCount;
+    /**
+     * 完播次数
+     */
+    private Integer finishCount;
+    /**
+     * 累计时长
+     */
+    private Integer watchTime;
+    /**
+     * 红包领取状态
+     */
+    private Integer redStatus;
+    /**
+     * 观看时间
+     */
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    private LocalDateTime watchDate;
+    /**
+     * 标签
+     */
+    private List<CompanyTag> tags;
+}

+ 52 - 0
fs-service-system/src/main/java/com/fs/course/vo/newfs/FsCourseAnalysisCountVO.java

@@ -0,0 +1,52 @@
+package com.fs.course.vo.newfs;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+import java.math.BigDecimal;
+
+@Data
+@ApiModel
+@Accessors(chain = true)
+public class FsCourseAnalysisCountVO implements Cloneable {
+
+    @ApiModelProperty(value = "关联视频id")
+    private Long videoId;
+
+    @ApiModelProperty(value = "观看人数")
+    private int courseWatchNum;
+
+    @ApiModelProperty(value = "完播人数")
+    private int courseCompleteNum;
+
+    @ApiModelProperty(value = "完播率")
+    private BigDecimal completeRate;
+
+    @ApiModelProperty(value = "答题红包数")
+    private int redPacketNum;
+
+    @ApiModelProperty(value = "答题红包金额")
+    private BigDecimal redPacketAmount;
+
+    @ApiModelProperty(value = "答题人数")
+    private int answerNum;
+
+    @ApiModelProperty(value = "正确人数")
+    private int answerRightNum;
+
+    @ApiModelProperty(value = "正确率")
+    private BigDecimal answerRightRate;
+
+    @Override
+    public FsCourseAnalysisCountVO clone() {
+        FsCourseAnalysisCountVO countVO;
+        try {
+            countVO = (FsCourseAnalysisCountVO) super.clone();
+        } catch (CloneNotSupportedException e) {
+            throw new AssertionError();
+        }
+        return countVO;
+    }
+}

+ 43 - 0
fs-service-system/src/main/java/com/fs/course/vo/newfs/FsCourseAnalysisVO.java

@@ -0,0 +1,43 @@
+package com.fs.course.vo.newfs;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+@Data
+@ApiModel
+public class FsCourseAnalysisVO implements Cloneable{
+
+    @ApiModelProperty(value = "课程id")
+    private Long courseId;
+
+    @ApiModelProperty(value = "课程名称")
+    private String courseName;
+
+    @ApiModelProperty(value = "关联视频id")
+    private Long videoId;
+
+    @ApiModelProperty(value = "视频标题")
+    private String title;
+
+    @ApiModelProperty(value = "视频封面")
+    private String thumbnail;
+
+    @ApiModelProperty(value = "统计信息")
+    private FsCourseAnalysisCountVO countVO;
+
+    /**
+     * 深度克隆
+     */
+    @Override
+    public FsCourseAnalysisVO clone() {
+        FsCourseAnalysisVO vo;
+        try {
+            vo = (FsCourseAnalysisVO) super.clone();
+        } catch (CloneNotSupportedException e) {
+            throw new AssertionError();
+        }
+        vo.countVO = countVO.clone();
+        return vo;
+    }
+}

+ 7 - 4
fs-service-system/src/main/java/com/fs/sop/service/impl/SopUserLogsInfoServiceImpl.java

@@ -448,7 +448,7 @@ public class SopUserLogsInfoServiceImpl implements ISopUserLogsInfoService {
                             addWatchLogIfNeeded(param.getSopId(), param.getVideoId(), param.getCourseId(),item.getFsUserId(), qwUserId, companyUserId, companyId, item.getExternalId(),param.getStartTime(),createTime );
 
                             String sortLink = generateShortLink(st, param.getCorpId(), createTime, param.getCourseId(), param.getVideoId(),
-                                    qwUserId, companyUserId, companyId,finalDomainName, item.getExternalId(),config);
+                                    qwUserId, companyUserId, companyId,finalDomainName, item.getExternalId(),config,contact.getFsUserId());
 
                             if (StringUtils.isNotEmpty(sortLink)) {
                                 if ("3".equals(st.getContentType())) {
@@ -481,7 +481,7 @@ public class SopUserLogsInfoServiceImpl implements ISopUserLogsInfoService {
                         addWatchLogIfNeeded(param.getSopId(), param.getVideoId(), param.getCourseId(),item.getFsUserId(), qwUserId, companyUserId, companyId, item.getExternalId(),param.getStartTime(),createTime );
 
                         String linkByMiniApp = createLinkByMiniApp(st, param.getCorpId(), createTime, param.getCourseId(), param.getVideoId(),
-                                qwUserId, companyUserId, companyId, item.getExternalId(), config);
+                                qwUserId, companyUserId, companyId, item.getExternalId(), config,contact.getFsUserId());
 
                         st.setMiniprogramPage(linkByMiniApp);
                         break;
@@ -602,7 +602,7 @@ public class SopUserLogsInfoServiceImpl implements ISopUserLogsInfoService {
 
     private String generateShortLink(QwSopCourseFinishTempSetting.Setting setting, String corpId, Date sendTime,
                                      Integer courseId, Integer videoId, String qwUserId,
-                                     String companyUserId, String companyId,String domainName, Long externalId,CourseConfig config) {
+                                     String companyUserId, String companyId,String domainName, Long externalId,CourseConfig config,Long FsUserId) {
 
         // 手动创建 FsCourseLink 对象,避免使用 BeanUtils.copyProperties
 //        FsCourseLink link = new FsCourseLink();
@@ -633,6 +633,7 @@ public class SopUserLogsInfoServiceImpl implements ISopUserLogsInfoService {
 
         FsCourseRealLink courseMap = new FsCourseRealLink();
         BeanUtils.copyProperties(link,courseMap);
+        courseMap.setFsUserId(FsUserId);
 
         String courseJson = JSON.toJSONString(courseMap);
         String realLinkFull = REAL_LINK_PREFIX + courseJson;
@@ -652,13 +653,14 @@ public class SopUserLogsInfoServiceImpl implements ISopUserLogsInfoService {
 
     private String createLinkByMiniApp(QwSopCourseFinishTempSetting.Setting setting, String corpId, Date sendTime,
                                      Integer courseId, Integer videoId, String qwUserId,
-                                     String companyUserId, String companyId, Long externalId,CourseConfig config) {
+                                     String companyUserId, String companyId, Long externalId,CourseConfig config,Long FsUserId) {
 
         FsCourseLink link = createFsCourseLink(corpId, sendTime, courseId, videoId, qwUserId,
                                                 companyUserId, companyId, externalId,3);
 
         FsCourseRealLink courseMap = new FsCourseRealLink();
         BeanUtils.copyProperties(link,courseMap);
+        courseMap.setFsUserId(FsUserId);
 
         String courseJson = JSON.toJSONString(courseMap);
         String realLinkFull = miniappRealLink + courseJson;
@@ -682,6 +684,7 @@ public class SopUserLogsInfoServiceImpl implements ISopUserLogsInfoService {
 
         FsCourseRealLink courseMap = new FsCourseRealLink();
         BeanUtils.copyProperties(link,courseMap);
+        courseMap.setFsUserId(fsUserId);
 
         String courseJson = JSON.toJSONString(courseMap);
         String realLinkFull = REAL_LINK_PREFIX + courseJson;

+ 16 - 4
fs-service-system/src/main/java/com/fs/store/mapper/FsUserMapper.java

@@ -3,6 +3,7 @@ package com.fs.store.mapper;
 import java.util.List;
 import java.util.Map;
 
+import com.fs.course.vo.newfs.FsCourseAnalysisCountVO;
 import com.fs.qw.param.QwFsUserParam;
 import com.fs.qw.vo.QwFsUserVO;
 import com.fs.qw.vo.newvo.ExternalContactNumVO;
@@ -10,7 +11,9 @@ import com.fs.store.domain.FsStorePayment;
 import com.fs.store.domain.FsUser;
 import com.fs.store.dto.FsUserTransferParamDTO;
 import com.fs.store.param.SelectCusListPageParam;
+import com.fs.store.param.h5.CourseAnalysisParam;
 import com.fs.store.param.h5.FsUserPageListParam;
+import com.fs.store.param.h5.UserStatisticsCommonParam;
 import com.fs.store.vo.FSUserVO;
 
 import com.fs.store.vo.FsCompanyUserListQueryVO;
@@ -241,13 +244,13 @@ public interface FsUserMapper
 
     List<FsUserSummaryCountTagVO> countTag(@Param("userId") Long userId);
 
-    Map<String, Long> countUserCourse(@Param("userId") Long userId, @Param("startTime") String startTime, @Param("endTime") String endTime, @Param("courseId")String courseId, @Param("videoId")String videoId);
+    Map<String, Long> countUserCourse(UserStatisticsCommonParam param);
 
-    Map<String, Long> countUserAnswer(@Param("userId") Long userId, @Param("startTime") String startTime, @Param("endTime") String endTime, @Param("courseId")String courseId, @Param("videoId")String videoId);
+    Map<String, Long> countUserAnswer(UserStatisticsCommonParam param);
 
-    Map<String, Object> countUserRedPacket(@Param("userId") Long userId, @Param("startTime") String startTime, @Param("endTime") String endTime, @Param("courseId")String courseId, @Param("videoId")String videoId);
+    Map<String, Object> countUserRedPacket(UserStatisticsCommonParam param);
 
-    Map<String, Long> countCourseDetails(@Param("userId") Long userId, @Param("courseId")String courseId, @Param("videoId")String videoId,  @Param("companyId")Long companyId);
+    Map<String, Long> countCourseDetails(UserStatisticsCommonParam param);
 
     List<FsUserRankingVO> countUserRankingByComplete(@Param("userId") Long userId, @Param("startTime") String startTime, @Param("endTime") String endTime, @Param("courseId")String courseId, @Param("videoId")String videoId, @Param("order")String order);
 
@@ -257,4 +260,13 @@ public interface FsUserMapper
 
     List<FsCourseRankingVO> countCourseRankingByRight(@Param("userId") Long userId, @Param("startTime") String startTime, @Param("endTime") String endTime, @Param("courseId")String courseId, @Param("videoId")String videoId, @Param("order")String order);
 
+    List<FsCourseAnalysisCountVO> courseAnalysisCourseCount(CourseAnalysisParam param);
+
+    List<FsCourseAnalysisCountVO> courseAnalysisRedPacketCount(CourseAnalysisParam param);
+
+    List<FsCourseAnalysisCountVO> courseAnalysisAnswerCount(CourseAnalysisParam param);
+
+    CompanyUserSummaryCountVO companyUserCount(@Param("companyUserId")String companyUserId);
+
+    CompanyUserSummaryCountVO newUserRedPacketCount(@Param("companyUserId")String companyUserId);
 }

+ 37 - 0
fs-service-system/src/main/java/com/fs/store/param/h5/CourseAnalysisParam.java

@@ -0,0 +1,37 @@
+package com.fs.store.param.h5;
+
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * 课程分析查询-入参
+ */
+@Data
+public class CourseAnalysisParam implements Serializable {
+
+    @ApiModelProperty(value = "页码,默认为1", required = true)
+    private Integer pageNum = 1;
+
+    @ApiModelProperty(value = "页大小,默认为10", required = true)
+    private Integer pageSize = 10;
+
+    @ApiModelProperty(value = "销售用户id")
+    private Long companyUserId;
+
+    @ApiModelProperty(value = "课程id")
+    private String courseId;
+
+    @ApiModelProperty(value = "视频id")
+    private String videoId;
+
+//    @ApiModelProperty(value = "登录用户id,不传")
+//    private Long userId;
+
+    @ApiModelProperty(value = "公司id,不传")
+    private Long companyId;
+
+}
+

+ 40 - 0
fs-service-system/src/main/java/com/fs/store/param/h5/UserStatisticsCommonParam.java

@@ -0,0 +1,40 @@
+package com.fs.store.param.h5;
+
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+import java.io.Serializable;
+
+/**
+ * 课程分析查询-入参
+ */
+@Data
+@Accessors(chain = true)
+public class UserStatisticsCommonParam implements Serializable {
+
+    @ApiModelProperty(value = "登录用户id,不传")
+    private Long userId;
+
+    @ApiModelProperty(value = "开始时间")
+    private String startTime;
+
+    @ApiModelProperty(value = "结束时间")
+    private String endTime;
+
+    @ApiModelProperty(value = "课程id")
+    private String courseId;
+
+    @ApiModelProperty(value = "视频id")
+    private String videoId;
+
+    @ApiModelProperty(value = "公司id")
+    private Long companyId;
+
+    @ApiModelProperty(value = "群管(二级销售)id")
+    private String companyUserId;
+
+
+}
+

+ 25 - 17
fs-service-system/src/main/java/com/fs/store/service/IFsUserService.java

@@ -6,6 +6,7 @@ import java.util.Map;
 import com.fs.common.core.domain.R;
 import com.fs.common.core.page.TableDataInfo;
 import com.fs.company.vo.CompanyQueryVo;
+import com.fs.course.vo.newfs.FsCourseAnalysisVO;
 import com.fs.qw.param.QwFsUserParam;
 import com.fs.qw.vo.QwFsUserVO;
 import com.fs.store.domain.FsStoreOrder;
@@ -13,7 +14,9 @@ import com.fs.store.domain.FsStoreOrderItem;
 import com.fs.store.domain.FsUser;
 import com.fs.store.dto.FsUserTransferParamDTO;
 import com.fs.store.param.SelectCusListPageParam;
+import com.fs.store.param.h5.CourseAnalysisParam;
 import com.fs.store.param.h5.FsUserPageListParam;
+import com.fs.store.param.h5.UserStatisticsCommonParam;
 import com.fs.store.vo.FSUserVO;
 import com.fs.store.vo.FsCompanyUserListQueryVO;
 import com.fs.store.vo.FsUserTuiVO;
@@ -163,23 +166,17 @@ public interface IFsUserService
 
     /**
      * 首页数据统计-课程、答题、红包统计
-     * @param userId 登录用户id
-     * @param startTime 开始时间
-     * @param endTime 结束时间
-     * @param courseId 课程id
-     * @param videoId 视频id
+     * @param param 查询参数
      * @return vo
      */
-    FsUserStatisticsVO userStatistics(Long userId, String startTime, String endTime, String courseId, String videoId);
+    FsUserStatisticsVO userStatistics(UserStatisticsCommonParam param);
 
     /**
      * 数据详情统计-根据课程id 视频id进行详情统计
-     * @param userId 登录用户id
-     * @param courseId 课程id
-     * @param videoId 视频id
+     * @param param 查询参数
      * @return vo
      */
-    FsUserStatisticsVO userStatisticsDetails(Long userId, String courseId, String videoId, Long companyId);
+    FsUserStatisticsVO userStatisticsDetails(UserStatisticsCommonParam param);
 
     /**
      * 首页数据/详情-获取群管排行榜统计
@@ -209,13 +206,24 @@ public interface IFsUserService
 
     /**
      *
-     * @param userId 用户id
-     * @param startTime 开始时间
-     * @param endTime 结束时间
-     * @param courseId 课程id
-     * @param videoId 视频id
-     * @return
+     * @param param 查询参数
+     * @return vo
+     */
+    List<FsUserGraphicStatisticsVO> graphicStatistics(UserStatisticsCommonParam param);
+
+    /**
+     * 课程分析查询-某销售下课程视频的观看和答题情况统计
+     * @param param 参数
+     * @return vo
+     */
+    List<FsCourseAnalysisVO> courseAnalysis(CourseAnalysisParam param);
+
+    /**
+     * 查询某个群管(二级销售)的会员统计
+     * @param userId 登录用户id
+     * @param companyUserId 销售id
+     * @return vo
      */
-    List<FsUserGraphicStatisticsVO> graphicStatistics(Long userId, String startTime, String endTime, String courseId, String videoId);
+    CompanyUserSummaryCountVO companyUserSummaryCount(Long userId, String companyUserId);
 
 }

+ 79 - 11
fs-service-system/src/main/java/com/fs/store/service/impl/FsUserServiceImpl.java

@@ -3,6 +3,7 @@ package com.fs.store.service.impl;
 import java.math.BigDecimal;
 import java.math.RoundingMode;
 import java.util.*;
+import java.util.function.Function;
 import java.util.stream.Collectors;
 
 
@@ -16,6 +17,11 @@ import com.fs.company.cache.ICompanyUserCacheService;
 import com.fs.company.domain.CompanyUser;
 import com.fs.company.service.ICompanyUserService;
 import com.fs.company.vo.CompanyQueryVo;
+import com.fs.course.mapper.FsUserCourseVideoMapper;
+import com.fs.course.param.newfs.UserCourseVideoPageParam;
+import com.fs.course.vo.newfs.FsCourseAnalysisCountVO;
+import com.fs.course.vo.newfs.FsCourseAnalysisVO;
+import com.fs.course.vo.newfs.FsUserCourseVideoPageListVO;
 import com.fs.qw.param.QwFsUserParam;
 import com.fs.qw.vo.QwFsUserVO;
 import com.fs.store.domain.FsStoreOrder;
@@ -26,8 +32,10 @@ import com.fs.store.dto.FsUserTransferParamDTO;
 import com.fs.store.enums.BillDetailEnum;
 import com.fs.store.mapper.FsStoreOrderMapper;
 import com.fs.store.mapper.FsStoreProductAttrValueMapper;
+import com.fs.store.param.h5.CourseAnalysisParam;
 import com.fs.store.param.h5.FsUserPageListParam;
 import com.fs.store.param.SelectCusListPageParam;
+import com.fs.store.param.h5.UserStatisticsCommonParam;
 import com.fs.store.service.IFsUserBillService;
 import com.fs.store.vo.FSUserVO;
 import com.fs.store.vo.FsCompanyUserListQueryVO;
@@ -75,6 +83,8 @@ public class FsUserServiceImpl implements IFsUserService
     private ICompanyUserCacheService companyUserCacheService;
     @Autowired
     private ICompanyUserService companyUserService;
+    @Autowired
+    private FsUserCourseVideoMapper userCourseVideoMapper;
 
     /**
      * 查询用户
@@ -480,15 +490,15 @@ public class FsUserServiceImpl implements IFsUserService
     }
 
     @Override
-    public FsUserStatisticsVO userStatistics(Long userId, String startTime, String endTime, String courseId, String videoId) {
-        return getUserStatistics(userId, startTime, endTime, courseId, videoId);
+    public FsUserStatisticsVO userStatistics(UserStatisticsCommonParam param) {
+        return getUserStatistics(param);
     }
 
-    private FsUserStatisticsVO getUserStatistics(Long userId, String startTime, String endTime, String courseId, String videoId) {
+    private FsUserStatisticsVO getUserStatistics(UserStatisticsCommonParam param) {
         FsUserStatisticsVO fsUserStatisticsVO = new FsUserStatisticsVO();
 
         // 获取课程统计
-        Map<String, Long> couserMap = fsUserMapper.countUserCourse(userId, startTime, endTime, courseId, videoId);
+        Map<String, Long> couserMap = fsUserMapper.countUserCourse(param);
         if (couserMap != null) {
             fsUserStatisticsVO.setCourseWatchNum(couserMap.get("courseWatchNum").intValue()).setCourseCompleteNum(couserMap.get("courseCompleteNum").intValue());
 
@@ -502,7 +512,7 @@ public class FsUserServiceImpl implements IFsUserService
         }
 
         // 获取答题统计
-        Map<String, Long> answerMap = fsUserMapper.countUserAnswer(userId, startTime, endTime, courseId, videoId);
+        Map<String, Long> answerMap = fsUserMapper.countUserAnswer(param);
         if (answerMap != null) {
             fsUserStatisticsVO.setAnswerNum(answerMap.get("answerNum").intValue()).setAnswerRightNum(answerMap.get("answerRightNum").intValue());
 
@@ -516,7 +526,7 @@ public class FsUserServiceImpl implements IFsUserService
         }
 
         // 获取红包统计
-        Map<String, Object> redPacketMap = fsUserMapper.countUserRedPacket(userId, startTime, endTime, courseId, videoId);
+        Map<String, Object> redPacketMap = fsUserMapper.countUserRedPacket(param);
         if(redPacketMap != null && redPacketMap.get("redPacketNum") != null && redPacketMap.get("redPacketAmount") != null) {
             fsUserStatisticsVO.setRedPacketNum(Integer.parseInt(redPacketMap.get("redPacketNum").toString()))
                     .setRedPacketAmount(new BigDecimal(redPacketMap.get("redPacketAmount").toString()));
@@ -525,11 +535,11 @@ public class FsUserServiceImpl implements IFsUserService
     }
 
     @Override
-    public FsUserStatisticsVO userStatisticsDetails(Long userId, String courseId, String videoId, Long companyId) {
-        FsUserStatisticsVO userStatisticsVO = getUserStatistics(userId, null, null, courseId, videoId);
+    public FsUserStatisticsVO userStatisticsDetails(UserStatisticsCommonParam param) {
+        FsUserStatisticsVO userStatisticsVO = getUserStatistics(param);
 
         //统计课程数据详情,在查询统计详情的时候需要显示
-        Map<String, Long> courseDetailsMap = fsUserMapper.countCourseDetails(userId, courseId, videoId, companyId);
+        Map<String, Long> courseDetailsMap = fsUserMapper.countCourseDetails(param);
         if(courseDetailsMap != null && courseDetailsMap.get("courseNum") != null && courseDetailsMap.get("videoNum") != null && courseDetailsMap.get("courseUserNum") != null){
             userStatisticsVO.setCourseNum(Integer.parseInt(courseDetailsMap.get("courseNum").toString()))
                     .setVideoNum(Integer.parseInt(courseDetailsMap.get("videoNum").toString()))
@@ -566,8 +576,8 @@ public class FsUserServiceImpl implements IFsUserService
     }
 
     @Override
-    public List<FsUserGraphicStatisticsVO> graphicStatistics(Long userId, String startTime, String endTime, String courseId, String videoId) {
-        FsUserStatisticsVO userStatistics = getUserStatistics(userId, startTime, endTime, courseId, videoId);
+    public List<FsUserGraphicStatisticsVO> graphicStatistics(UserStatisticsCommonParam param) {
+        FsUserStatisticsVO userStatistics = getUserStatistics(param);
         List<FsUserGraphicStatisticsVO> list = new ArrayList<>();
         list.add(new FsUserGraphicStatisticsVO("观看人数",userStatistics.getCourseWatchNum(), userStatistics.getCourseWatchNum()));
         list.add(new FsUserGraphicStatisticsVO("完播人数", userStatistics.getCourseCompleteNum(), userStatistics.getCourseCompleteNum()));
@@ -576,4 +586,62 @@ public class FsUserServiceImpl implements IFsUserService
         list.add(new FsUserGraphicStatisticsVO("答题红包数", userStatistics.getRedPacketNum(), userStatistics.getRedPacketNum()));
         return list;
     }
+
+    @Override
+    public List<FsCourseAnalysisVO> courseAnalysis(CourseAnalysisParam param) {
+        //1、查询课程视频信息
+        UserCourseVideoPageParam userCourseVideoPageParam = new UserCourseVideoPageParam();
+        BeanUtils.copyProperties(param, userCourseVideoPageParam);
+        List<FsUserCourseVideoPageListVO> videoList = userCourseVideoMapper.selectFsUserCourseVideoPageList(userCourseVideoPageParam);
+
+        //2、查询统计
+        List<FsCourseAnalysisCountVO> courseCountList = fsUserMapper.courseAnalysisCourseCount(param);
+        List<FsCourseAnalysisCountVO> redPacketCountList = fsUserMapper.courseAnalysisRedPacketCount(param);
+        List<FsCourseAnalysisCountVO> answerCountList = fsUserMapper.courseAnalysisAnswerCount(param);
+
+        //3、转化为map
+        Map<Long, FsCourseAnalysisCountVO> courseMap = courseCountList.stream()
+                .collect(Collectors.toMap(
+                        FsCourseAnalysisCountVO::getVideoId,
+                        Function.identity()
+                ));
+        Map<Long, FsCourseAnalysisCountVO> redPacketMap = redPacketCountList.stream()
+                .collect(Collectors.toMap(
+                        FsCourseAnalysisCountVO::getVideoId,
+                        Function.identity()
+                ));
+        Map<Long, FsCourseAnalysisCountVO> answerMap = answerCountList.stream()
+                .collect(Collectors.toMap(
+                        FsCourseAnalysisCountVO::getVideoId,
+                        Function.identity()
+                ));
+
+        //4、处理数据
+        return videoList.stream().map(v -> {
+            FsCourseAnalysisVO allVO = new FsCourseAnalysisVO();
+            BeanUtils.copyProperties(v, allVO);
+
+            FsCourseAnalysisCountVO countVO = new FsCourseAnalysisCountVO();
+            FsCourseAnalysisCountVO courseVO = courseMap.getOrDefault(v.getVideoId(), countVO);
+            FsCourseAnalysisCountVO redPacketVO = redPacketMap.getOrDefault(v.getVideoId(), countVO);
+            FsCourseAnalysisCountVO answerVO = answerMap.getOrDefault(v.getVideoId(), countVO);
+
+            BeanUtils.copyProperties(courseVO, countVO);
+            countVO.setRedPacketNum(redPacketVO.getRedPacketNum()).setRedPacketAmount(redPacketVO.getRedPacketAmount());
+            countVO.setAnswerNum(answerVO.getAnswerNum()).setAnswerRightNum(answerVO.getAnswerRightNum()).setAnswerRightRate(answerVO.getAnswerRightRate());
+            allVO.setCountVO(countVO);
+            return allVO;
+        }).collect(Collectors.toList());
+    }
+
+    @Override
+    public CompanyUserSummaryCountVO companyUserSummaryCount(Long userId, String companyUserId) {
+        CompanyUserSummaryCountVO companyUserCount = fsUserMapper.companyUserCount(companyUserId);
+        CompanyUserSummaryCountVO newUserRedPacketCount = fsUserMapper.newUserRedPacketCount(companyUserId);
+        CompanyUserSummaryCountVO vo = new CompanyUserSummaryCountVO();
+        BeanUtils.copyProperties(companyUserCount, vo);
+        vo.setUserRedPacketNum(newUserRedPacketCount.getUserRedPacketNum());
+        vo.setTodayUserRedPacketAmount(newUserRedPacketCount.getTodayUserRedPacketAmount());
+        return vo;
+    }
 }

+ 26 - 0
fs-service-system/src/main/java/com/fs/store/vo/h5/CompanyUserSummaryCountVO.java

@@ -0,0 +1,26 @@
+package com.fs.store.vo.h5;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+/**
+ *
+ */
+@Data
+@ApiModel
+public class CompanyUserSummaryCountVO {
+
+    @ApiModelProperty(value = "会员总数")
+    private int userTotal;
+
+    @ApiModelProperty(value = "今日新增会员")
+    private int todayNewUser;
+
+    @ApiModelProperty(value = "会员红包数")
+    private int userRedPacketNum;
+
+    @ApiModelProperty(value = "新会员红包金额")
+    private int todayUserRedPacketAmount;
+
+
+}

+ 13 - 2
fs-service-system/src/main/resources/mapper/company/CompanyTagMapper.xml

@@ -28,11 +28,15 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         where tag_id = #{tagId}
     </select>
 
+    <!-- 查询标签列表 -->
     <select id="selectCompanyTagListByMap" resultType="com.fs.company.domain.CompanyTag">
         select ct.* from company_tag ct
         <where>
-            <if test="params.keyword != null and params.keyword != ''">
-                ct.tab like concat('%', #{params.keyword}, '%')
+            <if test="params.keyword != null and params.keyword.length > 0">
+                and
+                <foreach collection="params.keyword" item="item"  open="(" separator="or" close=")">
+                    ct.tag like concat('%',#{item},'%')
+                </foreach>
             </if>
             <if test="params.companyId != null">
                 and ct.company_id = #{params.companyId}
@@ -40,6 +44,13 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         </where>
     </select>
 
+    <!-- 查询用户标签列表 -->
+    <select id="selectCompanyTagListByUserId" resultType="com.fs.company.domain.CompanyTag">
+        select ct.* from company_tag ct
+        inner join company_tag_user ctu on ctu.company_id = ct.company_id and find_in_set(ct.tag_id, ctu.tag_ids) > 0
+        where ctu.user_id = #{userId}
+    </select>
+
     <insert id="insertCompanyTag" parameterType="CompanyTag" useGeneratedKeys="true" keyProperty="tagId">
         insert into company_tag
         <trim prefix="(" suffix=")" suffixOverrides=",">

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

@@ -73,6 +73,12 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         </foreach>
     </delete>
 
+    <!-- 删除用户标签 -->
+    <delete id="deleteCompanyTagUserByMap">
+        delete from company_tag_user
+        where user_id = #{params.userId} and company_id = #{params.companyId} and company_user_id = #{params.companyUserId}
+    </delete>
+
     <select id="getTagList" resultType="CompanyUserTagListVO">
         SELECT
         company_tag.tag as tagName,
@@ -102,7 +108,10 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             fu.nickname as userName
         from company_tag_user ctu
         inner join fs_user fu on fu.user_id = ctu.user_id
-        where ctu.company_id = #{params.companyId} and find_in_set(#{params.tagId}, ctu.tag_ids)
+        where ctu.company_id = #{params.companyId} and
+        <foreach collection="params.tagIds" item="tagId" open="(" separator="or" close=")">
+            find_in_set(#{tagId}, ctu.tag_ids)
+        </foreach>
     </select>
 
 </mapper>

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

@@ -249,4 +249,68 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         ORDER BY
             c.course_id
     </select>
+
+    <!-- 查询用户参与记录 -->
+    <select id="getParticipationRecordByMap" resultType="com.fs.course.vo.FsUserCourseParticipationRecordVO">
+        select distinct
+            fu.user_id,
+            fuc.course_id,
+            fu.nickname as nickName,
+            fu.username as userName,
+            fu.avatar,
+            fu.phone as phoneNumber,
+            fu.create_time,
+            fcwl.create_time as watchDate,
+            ifnull(t1.watchCount, 0) as watchCount,
+            ifnull(t1.finishCount, 0) as finishCount,
+            ifnull(t1.watchTime, 0 ) as watchTime,
+            if(ifnull(t2.redcount, 0) > 0, 1, 0) AS redStatus
+        from fs_user_course fuc
+        inner join fs_course_watch_log fcwl on fcwl.course_id = fuc.course_id
+        inner join fs_user fu on fu.user_id = fcwl.user_id
+        left join (
+            select user_id,
+                count(log_id) AS watchCount,
+                count(case when log_type = 2 then log_id end) AS finishCount,
+                sum(duration) AS watchTime
+            from fs_course_watch_log
+            group by user_id
+        ) t1 on t1.user_id = fu.user_id
+        left join (
+            select user_id, course_id, count(log_id) as redcount
+            from fs_course_red_packet_log
+            group by user_id, course_id
+        ) t2 on t2.user_id = fu.user_id and t2.course_id = fuc.course_id
+        <if test="params.type == 0">
+            left join  (
+                select user_id, course_id, count(log_id) as count
+                from fs_course_answer_logs
+                where is_right = 1
+                group by user_id, course_id
+            ) t3 on t3.user_id = fu.user_id and t3.course_id = fuc.course_id
+        </if>
+        where fuc.course_id = #{params.courseId}
+        <if test="params.keyword != null and params.keyword != ''">
+            and (
+                fu.user_id = #{params.keyword}
+                or fu.nickname like concat('%', #{params.keyword}, '%')
+                or fu.username like concat('%', #{params.keyword}, '%')
+                or fu.phone = #{params.keyword}
+            )
+        </if>
+        <choose>
+            <when test="params.type == 0">
+                and t3.count > 0
+            </when>
+            <when test="params.type == 1">
+                and fcwl.log_type = 2
+            </when>
+            <when test="params.type == 2">
+                and fcwl.log_type in (1,4)
+            </when>
+            <otherwise>
+                and fcwl.log_type = 3
+            </otherwise>
+        </choose>
+    </select>
 </mapper>

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

@@ -179,9 +179,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         course.course_name
         FROM `fs_user_course_video` video
         LEFT JOIN fs_user_course course ON video.course_id = course.course_id
-        where 1 = 1
-        and course.is_del = 0
-        AND FIND_IN_SET(#{companyId}, course.company_ids)
+        where course.is_del = 0
         <if test="courseId != null and courseId !='' ">
             AND video.course_id = #{courseId}
         </if>

+ 164 - 4
fs-service-system/src/main/resources/mapper/store/FsUserMapper.xml

@@ -391,8 +391,8 @@
         fs_user_course_count.stop_watch_days,
         fs_user_course_count.create_time,
         fs_user_course_count.complete_watch_date,
-        company_tag.tag,
-        company_tag_user.tag_ids,
+        GROUP_CONCAT(DISTINCT company_tag.tag) AS tag,
+        GROUP_CONCAT(DISTINCT company_tag.tag_id) AS tagIds,
         company_user.nick_name as companyUserNickName
         FROM
         fs_user
@@ -668,6 +668,14 @@
                     <if test="videoId != null and videoId != ''">
                         AND fcv.video_id = #{videoId}
                     </if>
+                    <if test="videoId != null and videoId != ''">
+                        AND fcv.video_id = #{videoId}
+                    </if>
+                    -- 单独通过销售id查询
+                    <if test="companyUserId != null and companyUserId != ''">
+                        AND company_user.user_id = #{companyUserId}
+                    </if>
+
             ) as courseWatchNum,
             (
                 SELECT
@@ -692,6 +700,10 @@
                     <if test="videoId != null and videoId != ''">
                         AND fcv.video_id = #{videoId}
                     </if>
+                    -- 单独通过销售id查询
+                    <if test="companyUserId != null and companyUserId != ''">
+                        AND company_user.user_id = #{companyUserId}
+                    </if>
             ) as courseCompleteNum
     </select>
 
@@ -718,6 +730,10 @@
         <if test="videoId != null and videoId != ''">
             AND fs_course_answer_logs.video_id = #{videoId}
         </if>
+        -- 单独通过销售id查询
+        <if test="companyUserId != null and companyUserId != ''">
+            AND company_user.user_id = #{companyUserId}
+        </if>
         ) AS answerNum,
         (
         SELECT
@@ -741,6 +757,10 @@
         <if test="videoId != null and videoId != ''">
             AND fs_course_answer_logs.video_id = #{videoId}
         </if>
+        -- 单独通过销售id查询
+        <if test="companyUserId != null and companyUserId != ''">
+            AND company_user.user_id = #{companyUserId}
+        </if>
         ) AS answerRightNum
     </select>
 
@@ -767,6 +787,10 @@
                 <if test="videoId != null and videoId != ''">
                     AND flog.video_id = #{videoId}
                 </if>
+                -- 单独通过销售id查询
+                <if test="companyUserId != null and companyUserId != ''">
+                    AND company_user.user_id = #{companyUserId}
+                </if>
         ) AS redPacketNum,
         (
             SELECT
@@ -789,22 +813,34 @@
                 <if test="videoId != null and videoId != ''">
                     AND flog.video_id = #{videoId}
                 </if>
+                -- 单独通过销售id查询
+                <if test="companyUserId != null and companyUserId != ''">
+                    AND company_user.user_id = #{companyUserId}
+                </if>
         ) AS redPacketAmount
     </select>
 
     <select id="countCourseDetails" resultType="Map">
     select (SELECT count(DISTINCT fc.course_id)
             FROM fs_user_course fc
+            LEFT JOIN fs_user_course_count fcc ON fcc.course_id = fc.course_id
+            LEFT JOIN fs_user ON fs_user.user_id = fcc.user_id
             WHERE fc.is_del = 0
             AND FIND_IN_SET(#{companyId}, fc.company_ids)
             <if test="courseId != null and courseId != ''">
                 AND fc.course_id =  #{courseId}
             </if>
+            -- 单独通过销售id查询
+            <if test="companyUserId != null and companyUserId != ''">
+                AND fs_user.company_user_id = #{companyUserId}
+            </if>
             ) as courseNum,
 
            (SELECT count(DISTINCT fcv.video_id)
             FROM fs_user_course_video fcv
-                     LEFT JOIN fs_user_course fc ON fc.course_id = fcv.course_id
+            LEFT JOIN fs_user_course fc ON fc.course_id = fcv.course_id
+            LEFT JOIN fs_user_course_count fcc ON fcc.course_id = fc.course_id
+            LEFT JOIN fs_user ON fs_user.user_id = fcc.user_id
             WHERE fc.is_del = 0
             AND FIND_IN_SET(#{companyId}, fc.company_ids)
             <if test="courseId != null and courseId != ''">
@@ -813,14 +849,23 @@
             <if test="videoId != null and videoId != ''">
                 AND fcv.video_id = #{videoId}
             </if>
+            -- 单独通过销售id查询
+            <if test="companyUserId != null and companyUserId != ''">
+                AND fs_user.company_user_id = #{companyUserId}
+            </if>
             ) as videoNum,
-        ( SELECT count(DISTINCT user_id ) FROM fs_user_course_count fcc
+        ( SELECT count(DISTINCT fs_user.user_id ) FROM fs_user_course_count fcc
             LEFT JOIN fs_user_course_video fcv ON fcv.course_id = fcc.course_id
+            LEFT JOIN fs_user ON fs_user.user_id = fcc.user_id
         <if test="courseId != null and courseId != ''">
             AND fcc.course_id =  #{courseId}
         </if>
         <if test="videoId != null and videoId != ''">
             AND fcv.video_id = #{videoId}
+        </if>
+        -- 单独通过销售id查询
+        <if test="companyUserId != null and companyUserId != ''">
+            AND fs_user.company_user_id = #{companyUserId}
         </if>
          ) as courseUserNum
     </select>
@@ -996,4 +1041,119 @@
         LIMIT 20
     </select>
 
+    <!--  查询某用户的课程视频,看课统计  -->
+    <select id="courseAnalysisCourseCount" resultType="FsCourseAnalysisCountVO">
+        SELECT
+        count( DISTINCT fcc.user_id ) as courseWatchNum,
+        COUNT( DISTINCT CASE WHEN fcc.complete_watch_count > 0 THEN fcc.user_id END ) as courseCompleteNum,
+        ifnull(
+        ROUND(
+        (
+        COUNT( DISTINCT CASE WHEN fcc.complete_watch_count > 0 THEN fcc.user_id END ) / count( DISTINCT fcc.user_id )) * 100,
+        2
+        ),
+        0
+        ) as completeRate,
+        fcv.video_id
+        FROM
+        fs_user_course_count fcc
+        LEFT JOIN fs_user ON fs_user.user_id = fcc.user_id
+        LEFT JOIN company_user ON fs_user.company_user_id = company_user.user_id
+        LEFT JOIN fs_user_course_video fcv ON fcv.course_id = fcc.course_id
+        WHERE
+        company_user.user_id = #{companyUserId}
+          and fcv.is_del = 0
+        <if test="courseId != null and courseId != ''">
+            AND fcc.course_id =  #{courseId}
+        </if>
+        <if test="videoId != null and videoId != ''">
+            AND fcv.video_id = #{videoId}
+        </if>
+        GROUP BY
+        fcv.video_id
+    </select>
+
+    <!--  查询某用户的课程视频,红包统计  -->
+    <select id="courseAnalysisRedPacketCount" resultType="FsCourseAnalysisCountVO">
+        SELECT
+        count( flog.log_id ) as redPacketNum,
+        ifnull ( sum( flog.amount ), 0 ) as redPacketAmount,
+        flog.video_id
+        FROM
+        fs_course_red_packet_log flog
+        LEFT JOIN fs_user ON fs_user.user_id = flog.user_id
+        LEFT JOIN company_user ON company_user.user_id = fs_user.company_user_id
+        WHERE
+        company_user.user_id = #{companyUserId}
+        <if test="courseId != null and courseId != ''">
+            AND flog.course_id =  #{courseId}
+        </if>
+        <if test="videoId != null and videoId != ''">
+            AND flog.video_id = #{videoId}
+        </if>
+        GROUP BY
+        flog.video_id
+    </select>
+
+    <!--  查询某用户的课程视频,答题统计  -->
+    <select id="courseAnalysisAnswerCount" resultType="FsCourseAnalysisCountVO">
+        SELECT
+        count( DISTINCT fs_user.user_id ) as answerNum,
+        COUNT( DISTINCT CASE WHEN fs_course_answer_logs.is_right = 1 THEN fs_user.user_id END ) as answerRightNum,
+        ifnull(
+        ROUND(
+        (
+        COUNT( DISTINCT CASE WHEN fs_course_answer_logs.is_right = 1 THEN fs_user.user_id END ) / count( DISTINCT fs_user.user_id )) * 100,
+        2
+        ),
+        0
+        ) as answerRightRate,
+        fs_course_answer_logs.video_id
+        FROM
+        fs_course_answer_logs
+        LEFT JOIN fs_user ON fs_user.user_id = fs_course_answer_logs.user_id
+        LEFT JOIN company_user ON company_user.user_id = fs_user.company_user_id
+        WHERE
+        company_user.user_id = #{companyUserId}
+        <if test="courseId != null and courseId != ''">
+            AND fs_course_answer_logs.course_id =  #{courseId}
+        </if>
+        <if test="videoId != null and videoId != ''">
+            AND fs_course_answer_logs.video_id = #{videoId}
+        </if>
+        GROUP BY
+        fs_course_answer_logs.video_id
+    </select>
+
+    <select id="companyUserCount" resultType="CompanyUserSummaryCountVO">
+        SELECT
+            (
+                SELECT count( fs_user.user_id ) FROM fs_user LEFT JOIN company_user ON fs_user.company_user_id = company_user.user_id
+                WHERE company_user.user_id = #{companyUserId}
+            ) AS userTotal,
+            (
+                SELECT
+                    count( fs_user.user_id )
+                FROM
+                    fs_user
+                        LEFT JOIN company_user ON fs_user.company_user_id = company_user.user_id
+                WHERE
+                    company_user.user_id = #{companyUserId}
+                  AND to_days( fs_user.create_time ) = to_days(
+                        now())
+            ) AS todayNewUser
+    </select>
+
+    <select id="newUserRedPacketCount" resultType="CompanyUserSummaryCountVO">
+        SELECT
+            count(flog.log_id) as userRedPacketNum,
+            ifnull ( sum(case when to_days( fs_user.create_time ) = to_days(now()) THEN IFNULL(flog.amount,0) END), 0) as todayUserRedPacketAmount
+        FROM
+            fs_course_red_packet_log flog
+                LEFT JOIN fs_user ON fs_user.user_id = flog.user_id
+        WHERE
+            fs_user.company_user_id = #{companyUserId}
+    </select>
+
+
 </mapper>

+ 20 - 3
fs-user-app/src/main/java/com/fs/app/controller/CourseH5Controller.java

@@ -5,7 +5,9 @@ import cn.hutool.json.JSONUtil;
 import com.fs.app.annotation.Login;
 import com.fs.common.annotation.RepeatSubmit;
 import com.fs.common.core.domain.R;
+import com.fs.common.utils.StringUtils;
 import com.fs.course.config.CourseConfig;
+import com.fs.course.domain.FsCourseQuestionBank;
 import com.fs.course.domain.FsCourseWatchLog;
 import com.fs.course.param.FsCourseQuestionAnswerUParam;
 import com.fs.course.param.FsCourseSendRewardUParam;
@@ -13,15 +15,19 @@ import com.fs.course.param.FsUserCourseVideoFinishUParam;
 import com.fs.course.service.*;
 import com.fs.course.vo.FsUserCourseVideoH5DVO;
 import com.fs.course.vo.FsUserCourseVideoH5VO;
+import com.fs.course.vo.FsUserCourseVideoQuestionVO;
 import com.fs.system.service.ISysConfigService;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
 
 import javax.servlet.http.HttpServletRequest;
+import java.util.ArrayList;
+import java.util.List;
 
 @Api("h5课堂接口")
 @RestController
@@ -62,11 +68,23 @@ public class CourseH5Controller extends  AppBaseController{
         CourseConfig config = JSONUtil.toBean(json, CourseConfig.class);
         FsUserCourseVideoH5DVO course = courseService.selectFsUserCourseVideoH5DVOByVideoId(param.getVideoId());
 
+        List<FsUserCourseVideoQuestionVO> questionVOList = new ArrayList<>();
+        if (StringUtils.isNotEmpty(course.getQuestionBankId())){
+            String[] questionIds = course.getQuestionBankId().split(",");
+            for (String questionId : questionIds){
+                FsUserCourseVideoQuestionVO vo = new FsUserCourseVideoQuestionVO();
+                FsCourseQuestionBank questionBank = questionBankService.selectFsCourseQuestionBankById(Long.parseLong(questionId));
+                if (questionBank!=null&&questionBank.getStatus()!=0){
+                    BeanUtils.copyProperties(questionBank,vo);
+                    questionVOList.add(vo);
+                }
+            }
+        }
         Long duration = 0L;
         long tipsTime = 0L;
         int isFinish = 0;
         if (param.getLinkType()!=null&&param.getLinkType()==1){
-            return R.ok().put("course",course).put("config",config).put("playDuration",duration).put("tipsTime",tipsTime).put("maxBufferLength",config.getMaxBufferLength());
+            return R.ok().put("course",course).put("questions",questionVOList).put("config",config).put("playDuration",duration).put("tipsTime",tipsTime).put("maxBufferLength",config.getMaxBufferLength());
         }
         // 从Redis中获取观看时长
         String redisKey = "h5user:watch:duration:" + param.getQwUserId()+ ":" + param.getQwExternalId() + ":" + param.getVideoId();
@@ -94,8 +112,7 @@ public class CourseH5Controller extends  AppBaseController{
             redisCache.setCacheObject(videoRedisKey,course.getDuration());
         }
 
-        return R.ok().put("course",course).put("config",config).put("playDuration",duration).put("tipsTime",tipsTime).put("maxBufferLength",config.getMaxBufferLength()).put("isFinish",isFinish);
-    }
+        return R.ok().put("course",course).put("questions",questionVOList).put("config",config).put("playDuration",duration).put("tipsTime",tipsTime).put("maxBufferLength",config.getMaxBufferLength()).put("isFinish",isFinish);    }
 
 
 

+ 18 - 0
fs-user-app/src/main/java/com/fs/app/controller/WxMpController.java

@@ -14,6 +14,8 @@ import com.fs.qw.mapper.QwExternalContactMapper;
 import com.fs.sop.params.QwSopSettingTimeParam;
 
 import io.swagger.annotations.ApiOperation;
+import lombok.Synchronized;
+import me.chanjar.weixin.common.bean.WxJsapiSignature;
 import me.chanjar.weixin.common.bean.WxOAuth2UserInfo;
 import me.chanjar.weixin.common.bean.menu.WxMenu;
 import me.chanjar.weixin.common.bean.oauth2.WxOAuth2AccessToken;
@@ -28,6 +30,8 @@ import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
 
+import java.io.UnsupportedEncodingException;
+import java.net.URLDecoder;
 import java.text.SimpleDateFormat;
 import java.util.Calendar;
 import java.util.Date;
@@ -146,6 +150,20 @@ public class WxMpController {
 
     }
 
+    @GetMapping("/getWxConfig")
+    @Synchronized
+    public R getWxConfig(@RequestParam String url) throws WxErrorException {
+        try {
+            String sLink = URLDecoder.decode(url, "UTF-8");
+            final WxJsapiSignature jsapiSignature = wxMpService.createJsapiSignature(sLink);
+            return R.ok().put("data", jsapiSignature);
+        } catch (UnsupportedEncodingException e) {
+            // URL解码异常
+            return R.error(e.getMessage());
+        }
+
+    }
+