Browse Source

1、关闭读写分离
2、增加数据分级统计逻辑
3、

rayson 10 months ago
parent
commit
ae575acdf0
30 changed files with 665 additions and 143 deletions
  1. 8 2
      menduner/menduner-common/src/main/java/com/citu/module/menduner/common/db/TransformDataSourceInterceptor.java
  2. 0 1
      menduner/menduner-system-api/src/main/java/com/citu/module/menduner/system/enums/visits/MdeVisitsEnum.java
  3. 115 0
      menduner/menduner-system-biz/src/main/java/com/citu/module/menduner/system/controller/admin/analysis/AnalysisController.java
  4. 14 3
      menduner/menduner-system-biz/src/main/java/com/citu/module/menduner/system/controller/app/jobhunt/job/AppJobAdvertisedController.java
  5. 69 5
      menduner/menduner-system-biz/src/main/java/com/citu/module/menduner/system/controller/app/recruit/analysis/AppRecruitAnalysisController.java
  6. 2 22
      menduner/menduner-system-biz/src/main/java/com/citu/module/menduner/system/controller/app/recruit/person/cv/AppRecruitJobCvRelRespVO.java
  7. 4 3
      menduner/menduner-system-biz/src/main/java/com/citu/module/menduner/system/controller/base/analysis/AnalysisBaseReqVO.java
  8. 25 0
      menduner/menduner-system-biz/src/main/java/com/citu/module/menduner/system/controller/base/analysis/RecruitAnalysisReqVO.java
  9. 25 0
      menduner/menduner-system-biz/src/main/java/com/citu/module/menduner/system/controller/base/analysis/RecruitInterviewInviteAnalysisRespVO.java
  10. 15 0
      menduner/menduner-system-biz/src/main/java/com/citu/module/menduner/system/controller/base/analysis/RecruitJobAnalysisRespVO.java
  11. 23 0
      menduner/menduner-system-biz/src/main/java/com/citu/module/menduner/system/controller/base/analysis/RecruitJobCvRelAnalysisRespVO.java
  12. 33 0
      menduner/menduner-system-biz/src/main/java/com/citu/module/menduner/system/controller/base/job/JobCvRelSimpleRespVO.java
  13. 32 0
      menduner/menduner-system-biz/src/main/java/com/citu/module/menduner/system/dal/mysql/interview/InterviewInviteMapper.java
  14. 35 0
      menduner/menduner-system-biz/src/main/java/com/citu/module/menduner/system/dal/mysql/job/JobAdvertisedMapper.java
  15. 61 4
      menduner/menduner-system-biz/src/main/java/com/citu/module/menduner/system/dal/mysql/job/JobCvRelMapper.java
  16. 5 7
      menduner/menduner-system-biz/src/main/java/com/citu/module/menduner/system/dal/mysql/visits/MdeVisitsMapper.java
  17. 8 4
      menduner/menduner-system-biz/src/main/java/com/citu/module/menduner/system/mq/consumer/MdeVisitsConsumer.java
  18. 2 0
      menduner/menduner-system-biz/src/main/java/com/citu/module/menduner/system/mq/message/MdeVisitsSendMessage.java
  19. 21 11
      menduner/menduner-system-biz/src/main/java/com/citu/module/menduner/system/mq/producer/MdeVisitsProducer.java
  20. 1 1
      menduner/menduner-system-biz/src/main/java/com/citu/module/menduner/system/service/enterprise/EnterpriseServiceImpl.java
  21. 10 0
      menduner/menduner-system-biz/src/main/java/com/citu/module/menduner/system/service/interview/InterviewInviteService.java
  22. 19 0
      menduner/menduner-system-biz/src/main/java/com/citu/module/menduner/system/service/interview/InterviewInviteServiceImpl.java
  23. 6 0
      menduner/menduner-system-biz/src/main/java/com/citu/module/menduner/system/service/job/JobAdvertisedService.java
  24. 9 0
      menduner/menduner-system-biz/src/main/java/com/citu/module/menduner/system/service/job/JobAdvertisedServiceImpl.java
  25. 12 5
      menduner/menduner-system-biz/src/main/java/com/citu/module/menduner/system/service/job/JobCvRelService.java
  26. 29 66
      menduner/menduner-system-biz/src/main/java/com/citu/module/menduner/system/service/job/JobCvRelServiceImpl.java
  27. 1 1
      menduner/menduner-system-biz/src/main/java/com/citu/module/menduner/system/service/position/PositionServiceImpl.java
  28. 8 7
      menduner/menduner-system-biz/src/main/java/com/citu/module/menduner/system/service/visits/MdeVisitsServiceImpl.java
  29. 72 0
      menduner/menduner-system-biz/src/main/java/com/citu/module/menduner/system/util/RecruitAnalysisUtils.java
  30. 1 1
      menduner/menduner-system-biz/src/main/resources/application.yaml

+ 8 - 2
menduner/menduner-common/src/main/java/com/citu/module/menduner/common/db/TransformDataSourceInterceptor.java

@@ -1,5 +1,8 @@
 package com.citu.module.menduner.common.db;
 
+import com.baomidou.dynamic.datasource.annotation.DS;
+import com.baomidou.dynamic.datasource.annotation.Master;
+import com.baomidou.dynamic.datasource.annotation.Slave;
 import com.baomidou.dynamic.datasource.enums.DdConstants;
 import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
 import lombok.extern.slf4j.Slf4j;
@@ -15,6 +18,9 @@ import org.apache.ibatis.plugin.Signature;
 import org.apache.ibatis.session.ResultHandler;
 import org.apache.ibatis.session.RowBounds;
 
+import java.lang.annotation.Annotation;
+import java.util.Arrays;
+
 /**
  * 切换数据源拦截器
  * 读写分离   主写从读
@@ -35,13 +41,13 @@ public class TransformDataSourceInterceptor implements Interceptor {
         MappedStatement ms = (MappedStatement) args[0];
         String dataSource = null;
         try {
-             dataSource = DdConstants.MASTER;
+            dataSource = DdConstants.MASTER;
             if (SqlCommandType.SELECT == ms.getSqlCommandType()) {
                 // select
                 dataSource = DdConstants.SLAVE;
             }
             DynamicDataSourceContextHolder.push(dataSource);
-            log.info(" ----- use datasource ["+DynamicDataSourceContextHolder.peek()+"]  ----- ");
+            log.info(" ----- use datasource [" + DynamicDataSourceContextHolder.peek() + "]  ----- ");
             return invocation.proceed();
         } finally {
             if (null != dataSource) {

+ 0 - 1
menduner/menduner-system-api/src/main/java/com/citu/module/menduner/system/enums/visits/MdeVisitsEnum.java

@@ -11,7 +11,6 @@ import lombok.Getter;
 public enum MdeVisitsEnum {
 
     POSITION_CLICK("0", "职位类型点击"),
-
     POSITION_PUBLISH_CLICK("1", "发布职位点击"),
     ENTERPRISE_CLICK("2", "企业点击");
 

+ 115 - 0
menduner/menduner-system-biz/src/main/java/com/citu/module/menduner/system/controller/admin/analysis/AnalysisController.java

@@ -0,0 +1,115 @@
+package com.citu.module.menduner.system.controller.admin.analysis;
+
+import com.citu.framework.common.pojo.CommonResult;
+import com.citu.framework.common.pojo.PageResult;
+import com.citu.framework.security.core.annotations.PreAuthenticated;
+import com.citu.module.menduner.common.util.LoginUserContext;
+import com.citu.module.menduner.system.controller.base.CommonRespVO;
+import com.citu.module.menduner.system.controller.base.analysis.RecruitAnalysisReqVO;
+import com.citu.module.menduner.system.controller.base.analysis.RecruitInterviewInviteAnalysisRespVO;
+import com.citu.module.menduner.system.controller.base.analysis.RecruitJobAnalysisRespVO;
+import com.citu.module.menduner.system.controller.base.analysis.RecruitJobCvRelAnalysisRespVO;
+import com.citu.module.menduner.system.service.interview.InterviewInviteService;
+import com.citu.module.menduner.system.service.job.JobAdvertisedService;
+import com.citu.module.menduner.system.service.job.JobCvRelService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+import javax.validation.Valid;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import static com.citu.framework.common.pojo.CommonResult.success;
+
+@Tag(name = "管理后台 - 统计分析")
+@RestController
+@RequestMapping("/menduner/system/analysis")
+@Validated
+@Slf4j
+public class AnalysisController {
+
+    @Resource
+    private JobCvRelService jobCvcRelService;
+
+    @Resource
+    private InterviewInviteService interviewInviteService;
+
+    @Resource
+    private JobAdvertisedService jobAdvertisedService;
+
+    @GetMapping("/get/job/cv/sex/count")
+    @Operation(summary = "获取投递简历的性别分布")
+    @PreAuthenticated
+    public CommonResult<List<CommonRespVO>> getJobCvSexCount(@Valid RecruitAnalysisReqVO reqVO) {
+        return success(jobCvcRelService.getJobCvSexCount(reqVO));
+    }
+
+    @GetMapping("/get/job/cv/age/count")
+    @Operation(summary = "获取投递简历的年龄分布")
+    @PreAuthenticated
+    public CommonResult<Map<String, Object[]>> getJobCvAgeCount(@Valid RecruitAnalysisReqVO reqVO) {
+        return success(jobCvcRelService.getJobCvAgeCount(reqVO));
+    }
+
+    @GetMapping("/get/job/cv/edu/count")
+    @Operation(summary = "获取投递简历的学历分布")
+    @PreAuthenticated
+    public CommonResult<Map<String, Object[]>> getJobCvEduCount(@Valid RecruitAnalysisReqVO reqVO) {
+        return success(jobCvcRelService.getJobCvEduCount(reqVO));
+    }
+
+    @GetMapping("/get/job/cv/exp/count")
+    @Operation(summary = "获取投递简历的工作经验分布")
+    @PreAuthenticated
+    public CommonResult<Map<String, Object[]>> getJobCvExpCount(@Valid RecruitAnalysisReqVO reqVO) {
+        return success(jobCvcRelService.getJobCvExpCount(reqVO));
+    }
+
+    @GetMapping("/get/job/cv/new/page")
+    @Operation(summary = "获取新投递简历统计分析明细")
+    @PreAuthenticated
+    public CommonResult<PageResult<RecruitJobCvRelAnalysisRespVO>> getNewCvRel(
+            @Valid RecruitAnalysisReqVO reqVO) {
+        return success(jobCvcRelService.getNewCvRel(reqVO));
+    }
+
+    @GetMapping("/get/job/cv/look/page")
+    @Operation(summary = "获取已查看简历统计分析明细")
+    @PreAuthenticated
+    public CommonResult<PageResult<RecruitJobCvRelAnalysisRespVO>> getLookCvRel(
+            @Valid RecruitAnalysisReqVO reqVO) {
+        return success(jobCvcRelService.getLookCvRel(reqVO));
+    }
+
+    @GetMapping("/get/interview/wait/page")
+    @Operation(summary = "获取待面试统计分析明细")
+    @PreAuthenticated
+    public CommonResult<PageResult<RecruitInterviewInviteAnalysisRespVO>> getWaitInterview(
+            @Valid RecruitAnalysisReqVO reqVO) {
+        return success(interviewInviteService.getWaitInterview(reqVO));
+    }
+
+    @GetMapping("/get/interview/complete/page")
+    @Operation(summary = "获取完成面试统计分析明细")
+    @PreAuthenticated
+    public CommonResult<PageResult<RecruitInterviewInviteAnalysisRespVO>> getCompleteInterview(
+            @Valid RecruitAnalysisReqVO reqVO) {
+        return success(interviewInviteService.getCompleteInterview(reqVO));
+    }
+
+    @GetMapping("/get/job/browse/num/page")
+    @Operation(summary = "获取发布职位浏览量统计分析明细")
+    @PreAuthenticated
+    public CommonResult<PageResult<RecruitJobAnalysisRespVO>> getBrowseNum(
+            @Valid RecruitAnalysisReqVO reqVO) {
+        return success(jobAdvertisedService.getBrowseNum(reqVO));
+    }
+
+}

+ 14 - 3
menduner/menduner-system-biz/src/main/java/com/citu/module/menduner/system/controller/app/jobhunt/job/AppJobAdvertisedController.java

@@ -5,6 +5,8 @@ import com.citu.framework.common.pojo.PageParam;
 import com.citu.framework.common.pojo.PageResult;
 import com.citu.module.menduner.system.controller.app.jobhunt.job.vo.*;
 import com.citu.module.menduner.system.controller.base.CommonRespVO;
+import com.citu.module.menduner.system.enums.visits.MdeVisitsEnum;
+import com.citu.module.menduner.system.mq.producer.MdeVisitsProducer;
 import com.citu.module.menduner.system.service.job.JobAdvertisedService;
 import com.citu.module.menduner.system.service.job.JobIntegrationService;
 import io.swagger.v3.oas.annotations.Operation;
@@ -35,6 +37,9 @@ public class AppJobAdvertisedController {
     @Resource
     private JobIntegrationService jobIntegrationService;
 
+    @Resource
+    private MdeVisitsProducer visitsProducer;
+
     @GetMapping("/get/recommended")
     @Operation(summary = "获取推荐招聘职位分页")
     public CommonResult<PageResult<AppJobAdvertisedHomeRespVO>> getRecommendedPage(@Valid PageParam pageParam) {
@@ -65,7 +70,8 @@ public class AppJobAdvertisedController {
 
     @GetMapping("/get/acquainted")
     @Operation(summary = "获取相识职位信息分页")
-    public CommonResult<PageResult<AppJobAdvertisedHomeRespVO>> getAcquaintedPage(@Valid AppJobAdvertisedPageReqVO pageReqVO) {
+    public CommonResult<PageResult<AppJobAdvertisedHomeRespVO>> getAcquaintedPage
+            (@Valid AppJobAdvertisedPageReqVO pageReqVO) {
         PageResult<AppJobAdvertisedHomeRespVO> respVO = jobAdvertisedService.getAcquaintedPage(pageReqVO);
         return success(respVO);
     }
@@ -74,6 +80,9 @@ public class AppJobAdvertisedController {
     @Operation(summary = "获取招聘职位详情")
     public CommonResult<AppJobAdvertisedDetailRespVO> detail(@RequestParam("id") Long id) {
         AppJobAdvertisedDetailRespVO respVO = jobAdvertisedService.detail(id);
+        if (null != respVO) {
+            visitsProducer.send(MdeVisitsEnum.POSITION_PUBLISH_CLICK, id);
+        }
         return success(respVO);
     }
 
@@ -88,14 +97,16 @@ public class AppJobAdvertisedController {
 
     @GetMapping("/get/position/count")
     @Operation(summary = "根据企业id统计职位类型的数量")
-    public CommonResult<List<CommonRespVO>> getJobPositionCountByEnterpriseId(@RequestParam("enterpriseId") Long enterpriseId) {
+    public CommonResult<List<CommonRespVO>> getJobPositionCountByEnterpriseId
+            (@RequestParam("enterpriseId") Long enterpriseId) {
         List<CommonRespVO> list = jobAdvertisedService.getJobPositionCountByEnterpriseId(enterpriseId);
         return success(list);
     }
 
     @GetMapping("/get/area/count")
     @Operation(summary = "根据企业id获取企业职位区域")
-    public CommonResult<List<CommonRespVO>> getJobAreaCountByEnterpriseId(@RequestParam("enterpriseId") Long enterpriseId) {
+    public CommonResult<List<CommonRespVO>> getJobAreaCountByEnterpriseId
+            (@RequestParam("enterpriseId") Long enterpriseId) {
         List<CommonRespVO> list = jobAdvertisedService.getJobAreaCountByEnterpriseId(enterpriseId);
         return success(list);
     }

+ 69 - 5
menduner/menduner-system-biz/src/main/java/com/citu/module/menduner/system/controller/app/recruit/analysis/AppRecruitAnalysisController.java

@@ -1,9 +1,17 @@
 package com.citu.module.menduner.system.controller.app.recruit.analysis;
 
 import com.citu.framework.common.pojo.CommonResult;
+import com.citu.framework.common.pojo.PageResult;
 import com.citu.framework.security.core.annotations.PreAuthenticated;
-import com.citu.module.menduner.system.controller.app.recruit.analysis.vo.AppRecruitAnalysisReqVO;
+import com.citu.module.menduner.common.util.LoginUserContext;
+import com.citu.module.menduner.system.controller.base.analysis.RecruitAnalysisReqVO;
 import com.citu.module.menduner.system.controller.base.CommonRespVO;
+import com.citu.module.menduner.system.controller.base.analysis.RecruitInterviewInviteAnalysisRespVO;
+import com.citu.module.menduner.system.controller.base.analysis.RecruitJobAnalysisRespVO;
+import com.citu.module.menduner.system.controller.base.analysis.RecruitJobCvRelAnalysisRespVO;
+import com.citu.module.menduner.system.dal.mysql.interview.InterviewInviteMapper;
+import com.citu.module.menduner.system.service.interview.InterviewInviteService;
+import com.citu.module.menduner.system.service.job.JobAdvertisedService;
 import com.citu.module.menduner.system.service.job.JobCvRelService;
 import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.tags.Tag;
@@ -15,6 +23,7 @@ import org.springframework.web.bind.annotation.RestController;
 
 import javax.annotation.Resource;
 import javax.validation.Valid;
+import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 
@@ -30,33 +39,88 @@ public class AppRecruitAnalysisController {
     @Resource
     private JobCvRelService jobCvcRelService;
 
+    @Resource
+    private InterviewInviteService interviewInviteService;
+
+    @Resource
+    private JobAdvertisedService jobAdvertisedService;
+
     @GetMapping("/get/job/cv/sex/count")
     @Operation(summary = "获取投递简历的性别分布")
     @PreAuthenticated
-    public CommonResult<List<CommonRespVO>> getJobCvSexCount(@Valid AppRecruitAnalysisReqVO reqVO) {
+    public CommonResult<List<CommonRespVO>> getJobCvSexCount(@Valid RecruitAnalysisReqVO reqVO) {
         return success(jobCvcRelService.getJobCvSexCount(reqVO));
     }
 
     @GetMapping("/get/job/cv/age/count")
     @Operation(summary = "获取投递简历的年龄分布")
     @PreAuthenticated
-    public CommonResult<Map<String, Object[]>> getJobCvAgeCount(@Valid AppRecruitAnalysisReqVO reqVO) {
+    public CommonResult<Map<String, Object[]>> getJobCvAgeCount(@Valid RecruitAnalysisReqVO reqVO) {
         return success(jobCvcRelService.getJobCvAgeCount(reqVO));
     }
 
     @GetMapping("/get/job/cv/edu/count")
     @Operation(summary = "获取投递简历的学历分布")
     @PreAuthenticated
-    public CommonResult<Map<String, Object[]>> getJobCvEduCount(@Valid AppRecruitAnalysisReqVO reqVO) {
+    public CommonResult<Map<String, Object[]>> getJobCvEduCount(@Valid RecruitAnalysisReqVO reqVO) {
         return success(jobCvcRelService.getJobCvEduCount(reqVO));
     }
 
     @GetMapping("/get/job/cv/exp/count")
     @Operation(summary = "获取投递简历的工作经验分布")
     @PreAuthenticated
-    public CommonResult<Map<String, Object[]>> getJobCvExpCount(@Valid AppRecruitAnalysisReqVO reqVO) {
+    public CommonResult<Map<String, Object[]>> getJobCvExpCount(@Valid RecruitAnalysisReqVO reqVO) {
         return success(jobCvcRelService.getJobCvExpCount(reqVO));
     }
 
+    @GetMapping("/get/job/cv/new/page")
+    @Operation(summary = "获取新投递简历统计分析明细")
+    @PreAuthenticated
+    public CommonResult<PageResult<RecruitJobCvRelAnalysisRespVO>> getNewCvRel(
+            @Valid RecruitAnalysisReqVO reqVO) {
+        setCommonCondition(reqVO);
+        return success(jobCvcRelService.getNewCvRel(reqVO));
+    }
+
+    @GetMapping("/get/job/cv/look/page")
+    @Operation(summary = "获取已查看简历统计分析明细")
+    @PreAuthenticated
+    public CommonResult<PageResult<RecruitJobCvRelAnalysisRespVO>> getLookCvRel(
+            @Valid RecruitAnalysisReqVO reqVO) {
+        setCommonCondition(reqVO);
+        return success(jobCvcRelService.getLookCvRel(reqVO));
+    }
+
+    @GetMapping("/get/interview/wait/page")
+    @Operation(summary = "获取待面试统计分析明细")
+    @PreAuthenticated
+    public CommonResult<PageResult<RecruitInterviewInviteAnalysisRespVO>> getWaitInterview(
+            @Valid RecruitAnalysisReqVO reqVO) {
+        setCommonCondition(reqVO);
+        return success(interviewInviteService.getWaitInterview(reqVO));
+    }
+
+    @GetMapping("/get/interview/complete/page")
+    @Operation(summary = "获取完成面试统计分析明细")
+    @PreAuthenticated
+    public CommonResult<PageResult<RecruitInterviewInviteAnalysisRespVO>> getCompleteInterview(
+            @Valid RecruitAnalysisReqVO reqVO) {
+        setCommonCondition(reqVO);
+        return success(interviewInviteService.getCompleteInterview(reqVO));
+    }
+
+    @GetMapping("/get/job/browse/num/page")
+    @Operation(summary = "获取发布职位浏览量统计分析明细")
+    @PreAuthenticated
+    public CommonResult<PageResult<RecruitJobAnalysisRespVO>> getBrowseNum(
+            @Valid RecruitAnalysisReqVO reqVO) {
+        setCommonCondition(reqVO);
+        return success(jobAdvertisedService.getBrowseNum(reqVO));
+    }
+
+    private void setCommonCondition(RecruitAnalysisReqVO reqVO) {
+        reqVO.setEnterpriseId(LoginUserContext.getEnterpriseId());
+        reqVO.setUserId(Collections.singletonList(LoginUserContext.getUserId()));
+    }
 
 }

+ 2 - 22
menduner/menduner-system-biz/src/main/java/com/citu/module/menduner/system/controller/app/recruit/person/cv/AppRecruitJobCvRelRespVO.java

@@ -2,6 +2,7 @@ package com.citu.module.menduner.system.controller.app.recruit.person.cv;
 
 import com.citu.module.menduner.system.controller.app.recruit.person.vo.AppRecruitPersonSimpleRespVO;
 import com.citu.module.menduner.system.controller.app.recruit.job.vo.AppRecruitJobSimpleRespVO;
+import com.citu.module.menduner.system.controller.base.job.JobCvRelSimpleRespVO;
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
@@ -10,28 +11,7 @@ import java.time.LocalDateTime;
 
 @Schema(description = "menduner - 招聘职位简历投递分页 Response VO")
 @Data
-public class AppRecruitJobCvRelRespVO {
-
-    @Schema(description = "id", example = "24200")
-    private Long id;
-
-    @Schema(description = "简历附件标题")
-    private String title;
-
-    @Schema(description = "简历附件地址")
-    private String url;
-
-    @Schema(description = "投递用户id")
-    private Long userId;
-
-    @Schema(description = "投递类型(0 平台投递 | 1 赏金投递)")
-    private String type;
-
-    @Schema(description = "简历状态")
-    private String status;
-
-    @Schema(description = "更新时间")
-    private LocalDateTime updateTime;
+public class AppRecruitJobCvRelRespVO extends JobCvRelSimpleRespVO {
 
     @Schema(description = "投递人员信息")
     private AppRecruitPersonSimpleRespVO person;

+ 4 - 3
menduner/menduner-system-biz/src/main/java/com/citu/module/menduner/system/controller/app/recruit/analysis/vo/AppRecruitAnalysisReqVO.java → menduner/menduner-system-biz/src/main/java/com/citu/module/menduner/system/controller/base/analysis/AnalysisBaseReqVO.java

@@ -1,5 +1,6 @@
-package com.citu.module.menduner.system.controller.app.recruit.analysis.vo;
+package com.citu.module.menduner.system.controller.base.analysis;
 
+import com.citu.framework.common.pojo.PageParam;
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 import org.springframework.format.annotation.DateTimeFormat;
@@ -8,9 +9,9 @@ import java.time.LocalDateTime;
 
 import static com.citu.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
 
-@Schema(description = "menduner - 统计分析 Request VO")
+@Schema(description = "统计分析公共 Request VO")
 @Data
-public class AppRecruitAnalysisReqVO {
+public class AnalysisBaseReqVO extends PageParam {
 
     public static final String TYPE_RECENT_7_DAYS = "0";
     public static final String TYPE_LAST_MONTH = "1";

+ 25 - 0
menduner/menduner-system-biz/src/main/java/com/citu/module/menduner/system/controller/base/analysis/RecruitAnalysisReqVO.java

@@ -0,0 +1,25 @@
+package com.citu.module.menduner.system.controller.base.analysis;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.util.List;
+
+@Schema(description = "menduner - 统计分析公共 Request VO")
+@Data
+public class RecruitAnalysisReqVO extends AnalysisBaseReqVO {
+
+    @Schema(description = "企业id")
+    private Long enterpriseId;
+
+    @Schema(description = "部门id")
+    private Long deptId;
+
+    @Schema(description = "用户id")
+    private List<Long> userId;
+
+    @Schema(description = "发布职位id")
+    private Long jobId;
+
+
+}

+ 25 - 0
menduner/menduner-system-biz/src/main/java/com/citu/module/menduner/system/controller/base/analysis/RecruitInterviewInviteAnalysisRespVO.java

@@ -0,0 +1,25 @@
+package com.citu.module.menduner.system.controller.base.analysis;
+
+
+import com.citu.module.menduner.system.controller.app.recruit.job.vo.AppRecruitJobSimpleRespVO;
+import com.citu.module.menduner.system.controller.app.recruit.person.vo.AppRecruitPersonSimpleRespVO;
+import com.citu.module.menduner.system.controller.base.interview.InterviewInviteRespVO;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+@Schema(description = "面试明细分析 Response VO")
+@Data
+public class RecruitInterviewInviteAnalysisRespVO extends InterviewInviteRespVO {
+
+    @Schema(description = "更新时间")
+    private LocalDateTime updateTime;
+
+    @Schema(description = "人才简易信息")
+    private AppRecruitPersonSimpleRespVO person;
+
+    @Schema(description = "招聘职位信息")
+    private AppRecruitJobSimpleRespVO job;
+
+}

+ 15 - 0
menduner/menduner-system-biz/src/main/java/com/citu/module/menduner/system/controller/base/analysis/RecruitJobAnalysisRespVO.java

@@ -0,0 +1,15 @@
+package com.citu.module.menduner.system.controller.base.analysis;
+
+
+import com.citu.module.menduner.system.controller.base.job.JobAdvertisedSimpleRespVO;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+@Schema(description = "招聘职位明细分析 Response VO")
+@Data
+public class RecruitJobAnalysisRespVO extends JobAdvertisedSimpleRespVO {
+
+    @Schema(description = "浏览量")
+    private Long num;
+
+}

+ 23 - 0
menduner/menduner-system-biz/src/main/java/com/citu/module/menduner/system/controller/base/analysis/RecruitJobCvRelAnalysisRespVO.java

@@ -0,0 +1,23 @@
+package com.citu.module.menduner.system.controller.base.analysis;
+
+import com.citu.module.menduner.system.controller.app.recruit.job.vo.AppRecruitJobSimpleRespVO;
+import com.citu.module.menduner.system.controller.app.recruit.person.vo.AppRecruitPersonSimpleRespVO;
+import com.citu.module.menduner.system.controller.base.job.JobCvRelSimpleRespVO;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+
+@Schema(description = "简历明细分析 Response VO")
+@Data
+public class RecruitJobCvRelAnalysisRespVO extends JobCvRelSimpleRespVO {
+
+    @Schema(description = "投递人员信息")
+    private AppRecruitPersonSimpleRespVO person;
+
+    @Schema(description = "推荐的人员信息")
+    private AppRecruitPersonSimpleRespVO recommendPerson;
+
+    @Schema(description = "招聘信息")
+    private AppRecruitJobSimpleRespVO job;
+
+}

+ 33 - 0
menduner/menduner-system-biz/src/main/java/com/citu/module/menduner/system/controller/base/job/JobCvRelSimpleRespVO.java

@@ -0,0 +1,33 @@
+package com.citu.module.menduner.system.controller.base.job;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+@Schema(description = "招聘职位简历投递简易 Response VO")
+@Data
+public class JobCvRelSimpleRespVO {
+
+    @Schema(description = "id", example = "24200")
+    private Long id;
+
+    @Schema(description = "简历附件标题")
+    private String title;
+
+    @Schema(description = "简历附件地址")
+    private String url;
+
+    @Schema(description = "投递用户id")
+    private Long userId;
+
+    @Schema(description = "投递类型(0 平台投递 | 1 赏金投递)")
+    private String type;
+
+    @Schema(description = "简历状态")
+    private String status;
+
+    @Schema(description = "更新时间")
+    private LocalDateTime updateTime;
+
+}

+ 32 - 0
menduner/menduner-system-biz/src/main/java/com/citu/module/menduner/system/dal/mysql/interview/InterviewInviteMapper.java

@@ -10,6 +10,8 @@ import com.citu.module.menduner.system.controller.app.jobhunt.interview.vo.AppIn
 import com.citu.module.menduner.system.controller.app.recruit.interview.vo.AppRecruitInterviewInviteReqPageVO;
 import com.citu.module.menduner.system.controller.app.recruit.interview.vo.AppRecruitInterviewInviteRespVO;
 import com.citu.module.menduner.system.controller.base.CommonRespVO;
+import com.citu.module.menduner.system.controller.base.analysis.RecruitAnalysisReqVO;
+import com.citu.module.menduner.system.controller.base.analysis.RecruitInterviewInviteAnalysisRespVO;
 import com.citu.module.menduner.system.controller.base.interview.InterviewInvitePageReqVO;
 import com.citu.module.menduner.system.dal.dataobject.enterprise.EnterpriseDO;
 import com.citu.module.menduner.system.dal.dataobject.interview.InterviewInviteDO;
@@ -180,6 +182,7 @@ public interface InterviewInviteMapper extends BaseMapperX<InterviewInviteDO> {
         return selectJoinList(InterviewInviteDO.class, query);
     }
 
+    /** 获取推荐职位面试会话状态数量 **/
     default List<CommonRespVO> getRecommendCount(Long userId) {
         MPJLambdaWrapperX<InterviewInviteDO> wrapper = new MPJLambdaWrapperX<>();
         wrapper.
@@ -199,5 +202,34 @@ public interface InterviewInviteMapper extends BaseMapperX<InterviewInviteDO> {
         return selectJoinList(CommonRespVO.class, wrapper);
     }
 
+    /**
+     * 面试邀约明细
+     *
+     * @param reqVO     公共条件
+     * @param startTime 开始时间
+     * @param endTime   结束时间
+     * @param status    面试状态
+     **/
+    default PageResult<RecruitInterviewInviteAnalysisRespVO> getAnalysisDetail(
+            RecruitAnalysisReqVO reqVO, LocalDateTime startTime, LocalDateTime endTime, String status) {
+        MPJLambdaWrapperX<InterviewInviteDO> query = new MPJLambdaWrapperX<>();
+        query.selectAll(InterviewInviteDO.class);
+        query.selectAssociation(PersonInfoDO.class, AppRecruitInterviewInviteRespVO::getPerson);
+        query.selectAssociation(JobAdvertisedDO.class, AppRecruitInterviewInviteRespVO::getJob);
+
+        query.innerJoin(PersonInfoDO.class, PersonInfoDO::getUserId, InterviewInviteDO::getUserId);
+        query.innerJoin(JobAdvertisedDO.class, JobAdvertisedDO::getId, InterviewInviteDO::getJobId);
+
+        query.eqIfPresent(InterviewInviteDO::getEnterpriseId, reqVO.getEnterpriseId());
+        query.inIfPresent(InterviewInviteDO::getInviteUserId, reqVO.getUserId());
+        query.eqIfPresent(InterviewInviteDO::getJobId, reqVO.getJobId());
+        query.eqIfPresent(InterviewInviteDO::getStatus, status);
+        query.eqIfPresent(InterviewInviteDO::getConversationStatus, ConversationStatusEnum.INVITE.getStatus());
+        query.between(JobCvRelDO::getCreateTime, startTime, endTime);
+
+        query.orderByDesc(InterviewInviteDO::getUpdateTime);
+
+        return selectJoinPage(reqVO, RecruitInterviewInviteAnalysisRespVO.class, query);
+    }
 
 }

+ 35 - 0
menduner/menduner-system-biz/src/main/java/com/citu/module/menduner/system/dal/mysql/job/JobAdvertisedMapper.java

@@ -14,11 +14,16 @@ import com.citu.module.menduner.system.controller.app.jobhunt.job.vo.AppJobAdver
 import com.citu.module.menduner.system.controller.app.jobhunt.job.vo.AppJobAdvertisedRespVO;
 import com.citu.module.menduner.system.controller.app.recruit.job.vo.AppRecruitJobPageReqVO;
 import com.citu.module.menduner.system.controller.app.recruit.job.vo.AppRecruitJobSimpleRespVO;
+import com.citu.module.menduner.system.controller.base.analysis.RecruitAnalysisReqVO;
+import com.citu.module.menduner.system.controller.base.analysis.RecruitJobAnalysisRespVO;
 import com.citu.module.menduner.system.controller.base.job.JobAdvertisedPageReqVO;
 import com.citu.module.menduner.system.dal.dataobject.enterprise.EnterpriseDO;
 import com.citu.module.menduner.system.dal.dataobject.job.JobAdvertisedDO;
+import com.citu.module.menduner.system.dal.dataobject.job.JobCvRelDO;
+import com.citu.module.menduner.system.dal.dataobject.visits.MdeVisitsDO;
 import com.citu.module.menduner.system.enums.MendunerStatusEnum;
 import com.citu.module.menduner.system.enums.job.JobStatusEnum;
+import com.citu.module.menduner.system.enums.visits.MdeVisitsEnum;
 import org.apache.ibatis.annotations.Mapper;
 
 import java.time.LocalDateTime;
@@ -177,4 +182,34 @@ public interface JobAdvertisedMapper extends BaseMapperX<JobAdvertisedDO> {
         return selectJoinList(AppRecruitJobSimpleRespVO.class, query);
     }
 
+    /**
+     * 职位浏览量明细
+     *
+     * @param reqVO     公共条件
+     * @param startTime 开始时间
+     * @param endTime   结束时间
+     **/
+    default PageResult<RecruitJobAnalysisRespVO> getAnalysisDetail(
+            RecruitAnalysisReqVO reqVO, LocalDateTime startTime, LocalDateTime endTime) {
+        MPJLambdaWrapperX<JobAdvertisedDO> query = new MPJLambdaWrapperX<>();
+        query.selectAll(JobAdvertisedDO.class);
+        query.selectSum(MdeVisitsDO::getCount,RecruitJobAnalysisRespVO::getNum);
+
+        query.eqIfPresent(JobAdvertisedDO::getEnterpriseId, reqVO.getEnterpriseId());
+        query.inIfPresent(JobAdvertisedDO::getUserId, reqVO.getUserId());
+        query.eqIfPresent(JobAdvertisedDO::getId, reqVO.getJobId());
+
+        query.innerJoin(MdeVisitsDO.class, on->
+                on.eq(MdeVisitsDO::getBizId,JobAdvertisedDO::getId)
+                        .eq(MdeVisitsDO::getType, MdeVisitsEnum.POSITION_PUBLISH_CLICK.getType())
+        );
+
+        query.between(MdeVisitsDO::getUpdateTime, startTime, endTime);
+
+        query.groupBy(JobAdvertisedDO::getId);
+        query.orderByDesc(MdeVisitsDO::getUpdateTime);
+
+        return selectJoinPage(reqVO,RecruitJobAnalysisRespVO.class, query);
+    }
+
 }

+ 61 - 4
menduner/menduner-system-biz/src/main/java/com/citu/module/menduner/system/dal/mysql/job/JobCvRelMapper.java

@@ -12,6 +12,8 @@ import com.citu.module.menduner.system.controller.app.recruit.person.cv.AppRecru
 import com.citu.module.menduner.system.controller.app.recruit.person.hire.AppRecruitHireJobCvRelPageReqVO;
 import com.citu.module.menduner.system.controller.app.recruit.person.hire.AppRecruitHireJobCvRelRespVO;
 import com.citu.module.menduner.system.controller.base.CommonRespVO;
+import com.citu.module.menduner.system.controller.base.analysis.RecruitAnalysisReqVO;
+import com.citu.module.menduner.system.controller.base.analysis.RecruitJobCvRelAnalysisRespVO;
 import com.citu.module.menduner.system.controller.base.job.JobCvRelPageReqVO;
 import com.citu.module.menduner.system.dal.dataobject.enterprise.EnterpriseDO;
 import com.citu.module.menduner.system.dal.dataobject.interview.InterviewInviteDO;
@@ -223,12 +225,17 @@ public interface JobCvRelMapper extends BaseMapperX<JobCvRelDO> {
     /**
      * 投递简历的性别比例
      **/
-    default List<CommonRespVO> getJobCvSexCount(LocalDateTime startTime, LocalDateTime endTime) {
+    default List<CommonRespVO> getJobCvSexCount
+    (RecruitAnalysisReqVO reqVO, LocalDateTime startTime, LocalDateTime endTime) {
         MPJLambdaWrapperX<JobCvRelDO> wrapper = new MPJLambdaWrapperX<>();
         wrapper.selectAs(PersonInfoDO::getSex, "`key`");
         wrapper.selectCount(JobCvRelDO::getId, CommonRespVO::getValue);
         wrapper.innerJoin(PersonInfoDO.class, PersonInfoDO::getUserId, JobCvRelDO::getUserId);
         wrapper.between(JobCvRelDO::getCreateTime, startTime, endTime);
+
+        wrapper.eqIfPresent(JobCvRelDO::getJobId, reqVO.getJobId());
+        wrapper.eqIfPresent(JobCvRelDO::getEnterpriseId, reqVO.getEnterpriseId());
+        wrapper.inIfPresent(JobCvRelDO::getUserId, reqVO.getUserId());
         wrapper.groupBy(PersonInfoDO::getSex);
         wrapper.orderByDesc("`key`");
         return selectJoinList(CommonRespVO.class, wrapper);
@@ -238,7 +245,8 @@ public interface JobCvRelMapper extends BaseMapperX<JobCvRelDO> {
     /**
      * 投递简历的年龄分布
      **/
-    default List<CommonRespVO> getJobCvAgeCount(LocalDateTime startTime, LocalDateTime endTime) {
+    default List<CommonRespVO> getJobCvAgeCount
+    (RecruitAnalysisReqVO reqVO, LocalDateTime startTime, LocalDateTime endTime) {
         MPJLambdaWrapperX<JobCvRelDO> wrapper = new MPJLambdaWrapperX<>();
 
         String sql = "CASE \n" +
@@ -255,6 +263,10 @@ public interface JobCvRelMapper extends BaseMapperX<JobCvRelDO> {
 
         wrapper.innerJoin(PersonInfoDO.class, PersonInfoDO::getUserId, JobCvRelDO::getUserId);
         wrapper.between(JobCvRelDO::getCreateTime, startTime, endTime);
+
+        wrapper.eqIfPresent(JobCvRelDO::getJobId, reqVO.getJobId());
+        wrapper.eqIfPresent(JobCvRelDO::getEnterpriseId, reqVO.getEnterpriseId());
+        wrapper.inIfPresent(JobCvRelDO::getUserId, reqVO.getUserId());
         wrapper.groupBy("`key`");
         wrapper.orderByDesc("`key`");
         return selectJoinList(CommonRespVO.class, wrapper);
@@ -263,13 +275,18 @@ public interface JobCvRelMapper extends BaseMapperX<JobCvRelDO> {
     /**
      * 投递简历的工作经验分布
      **/
-    default List<CommonRespVO> getJobCvExpCount(LocalDateTime startTime, LocalDateTime endTime) {
+    default List<CommonRespVO> getJobCvExpCount
+    (RecruitAnalysisReqVO reqVO, LocalDateTime startTime, LocalDateTime endTime) {
         MPJLambdaWrapperX<JobCvRelDO> wrapper = new MPJLambdaWrapperX<>();
         wrapper.selectAs(PersonInfoDO::getExpType, "`key`");
         wrapper.selectCount(JobCvRelDO::getId, CommonRespVO::getValue);
 
         wrapper.innerJoin(PersonInfoDO.class, PersonInfoDO::getUserId, JobCvRelDO::getUserId);
         wrapper.between(JobCvRelDO::getCreateTime, startTime, endTime);
+
+        wrapper.eqIfPresent(JobCvRelDO::getJobId, reqVO.getJobId());
+        wrapper.eqIfPresent(JobCvRelDO::getEnterpriseId, reqVO.getEnterpriseId());
+        wrapper.inIfPresent(JobCvRelDO::getUserId, reqVO.getUserId());
         wrapper.groupBy(PersonInfoDO::getExpType);
         wrapper.orderByDesc("`key`");
         return selectJoinList(CommonRespVO.class, wrapper);
@@ -278,18 +295,58 @@ public interface JobCvRelMapper extends BaseMapperX<JobCvRelDO> {
     /**
      * 投递简历的学历分布
      **/
-    default List<CommonRespVO> getJobCvEduCount(LocalDateTime startTime, LocalDateTime endTime) {
+    default List<CommonRespVO> getJobCvEduCount
+    (RecruitAnalysisReqVO reqVO, LocalDateTime startTime, LocalDateTime endTime) {
         MPJLambdaWrapperX<JobCvRelDO> wrapper = new MPJLambdaWrapperX<>();
         wrapper.selectAs(PersonInfoDO::getEduType, "`key`");
         wrapper.selectCount(JobCvRelDO::getId, CommonRespVO::getValue);
 
         wrapper.innerJoin(PersonInfoDO.class, PersonInfoDO::getUserId, JobCvRelDO::getUserId);
         wrapper.between(JobCvRelDO::getCreateTime, startTime, endTime);
+
+        wrapper.eqIfPresent(JobCvRelDO::getJobId, reqVO.getJobId());
+        wrapper.eqIfPresent(JobCvRelDO::getEnterpriseId, reqVO.getEnterpriseId());
+        wrapper.inIfPresent(JobCvRelDO::getUserId, reqVO.getUserId());
         wrapper.groupBy(PersonInfoDO::getEduType);
         wrapper.orderByDesc("`key`");
 
         return selectJoinList(CommonRespVO.class, wrapper);
     }
 
+    /**
+     * 简历明细
+     *
+     * @param reqVO     公共条件
+     * @param startTime 开始时间
+     * @param endTime   结束时间
+     * @param status    投递简历的状态
+     **/
+    default PageResult<RecruitJobCvRelAnalysisRespVO> getAnalysisDetail(
+            RecruitAnalysisReqVO reqVO, LocalDateTime startTime, LocalDateTime endTime, String status) {
+        MPJLambdaWrapperX<JobCvRelDO> wrapper = new MPJLambdaWrapperX<>();
+        wrapper.selectAsClass(JobCvRelDO.class, RecruitJobCvRelAnalysisRespVO.class);
+        wrapper.selectAssociation(JobAdvertisedDO.class, RecruitJobCvRelAnalysisRespVO::getJob);
+        wrapper.selectAssociation("person", PersonInfoDO.class, RecruitJobCvRelAnalysisRespVO::getPerson);
+        wrapper.selectAssociation("recommend", PersonInfoDO.class, RecruitJobCvRelAnalysisRespVO::getRecommendPerson);
+
+        wrapper.eqIfPresent(JobCvRelDO::getEnterpriseId, reqVO.getEnterpriseId());
+        wrapper.inIfPresent(JobCvRelDO::getPublishUserId, reqVO.getUserId());
+        wrapper.eqIfPresent(JobCvRelDO::getJobId, reqVO.getJobId());
+        wrapper.eqIfPresent(JobCvRelDO::getStatus, status);
+        wrapper.between(JobCvRelDO::getCreateTime, startTime, endTime);
+
+        // 投递的职位 inner 招聘职位
+        wrapper.innerJoin(JobAdvertisedDO.class, JobAdvertisedDO::getId, JobCvRelDO::getJobId);
+
+        // 投递的职位 inner 人才信息 (投递人)
+        wrapper.innerJoin(PersonInfoDO.class, "person", PersonInfoDO::getUserId, JobCvRelDO::getUserId);
+
+        // 投递的职位 inner 人才信息 (推荐人)
+        wrapper.leftJoin(PersonInfoDO.class, "recommend", PersonInfoDO::getUserId, JobCvRelDO::getRecommendUserId);
+
+        wrapper.orderByDesc(JobCvRelDO::getUpdateTime);
+        return selectJoinPage(reqVO, RecruitJobCvRelAnalysisRespVO.class, wrapper);
+    }
+
 
 }

+ 5 - 7
menduner/menduner-system-biz/src/main/java/com/citu/module/menduner/system/dal/mysql/visits/MdeVisitsMapper.java

@@ -33,7 +33,7 @@ public interface MdeVisitsMapper extends BaseMapperX<MdeVisitsDO> {
     }
 
 
-    default List<MdeVisitsDO> getBizIdVisitsTop10List(MdeVisitsListReqVO reqVO){
+    default List<MdeVisitsDO> getBizIdVisitsTop10List(MdeVisitsListReqVO reqVO) {
         return selectList(new LambdaQueryWrapperX<MdeVisitsDO>()
                 .eq(MdeVisitsDO::getUserId, reqVO.getUserId())
                 .eq(MdeVisitsDO::getType, reqVO.getType())
@@ -47,15 +47,13 @@ public interface MdeVisitsMapper extends BaseMapperX<MdeVisitsDO> {
     }
 
     default MdeVisitsDO getMdeVisitsByUserIdAndTypeAndBizIdAndDate(Long userId, String type, Long bizId, LocalDateTime date) {
-        LambdaQueryWrapperX<MdeVisitsDO> wrapperX =  new LambdaQueryWrapperX<MdeVisitsDO>()
+        LambdaQueryWrapperX<MdeVisitsDO> wrapperX = new LambdaQueryWrapperX<MdeVisitsDO>()
                 .eqIfPresent(MdeVisitsDO::getType, type)
                 .eqIfPresent(MdeVisitsDO::getBizId, bizId)
                 .eqIfPresent(MdeVisitsDO::getDate, date.format(DateTimeFormatter.ofPattern(DateUtils.FORMAT_YEAR_MONTH_DAY)));
-        if(null == userId) {
-            wrapperX.isNull(MdeVisitsDO::getUserId);
-        }else{
-            wrapperX.eqIfPresent(MdeVisitsDO::getUserId,userId);
-        }
+
+        wrapperX.eqIfPresent(MdeVisitsDO::getUserId, userId);
+
         return selectOne(wrapperX);
     }
 }

+ 8 - 4
menduner/menduner-system-biz/src/main/java/com/citu/module/menduner/system/mq/consumer/MdeVisitsConsumer.java

@@ -4,7 +4,8 @@ import com.citu.module.menduner.system.mq.message.MdeVisitsSendMessage;
 import com.citu.module.menduner.system.mq.producer.MdeVisitsProducer;
 import com.citu.module.menduner.system.service.visits.MdeVisitsService;
 import lombok.extern.slf4j.Slf4j;
-import org.springframework.context.event.EventListener;
+import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
+import org.apache.rocketmq.spring.core.RocketMQListener;
 import org.springframework.scheduling.annotation.Async;
 import org.springframework.stereotype.Component;
 
@@ -17,13 +18,16 @@ import javax.annotation.Resource;
  */
 @Component
 @Slf4j
-public class MdeVisitsConsumer {
+@RocketMQMessageListener(
+        topic = MdeVisitsSendMessage.VISITS_CLICK_TOPIC,
+        consumerGroup = MdeVisitsSendMessage.VISITS_CLICK_TOPIC + "_CONSUMER"
+)
+public class MdeVisitsConsumer implements RocketMQListener<MdeVisitsSendMessage> {
 
     @Resource
     private MdeVisitsService service;
 
-    @EventListener
-    @Async // Spring Event 默认在 Producer 发送的线程,通过 @Async 实现异步
+    @Override
     public void onMessage(MdeVisitsSendMessage message) {
         log.info("[onMessage][消息内容({})]", message);
         service.create(message);

+ 2 - 0
menduner/menduner-system-biz/src/main/java/com/citu/module/menduner/system/mq/message/MdeVisitsSendMessage.java

@@ -21,6 +21,8 @@ import static com.citu.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DA
 @Schema(description = "访问量新增")
 public class MdeVisitsSendMessage {
 
+    public static final String VISITS_CLICK_TOPIC = "VISITS_CLICK_TOPIC";
+
     @NotBlank(message = "{1_100_015_002}")
     @Schema(description = "业务类型")
     private String type;

+ 21 - 11
menduner/menduner-system-biz/src/main/java/com/citu/module/menduner/system/mq/producer/MdeVisitsProducer.java

@@ -1,8 +1,11 @@
 package com.citu.module.menduner.system.mq.producer;
 
+import com.citu.module.menduner.system.enums.visits.MdeVisitsEnum;
 import com.citu.module.menduner.system.mq.message.MdeVisitsSendMessage;
 import lombok.extern.slf4j.Slf4j;
-import org.springframework.context.ApplicationContext;
+import org.apache.rocketmq.spring.core.RocketMQTemplate;
+import org.springframework.messaging.Message;
+import org.springframework.messaging.support.MessageBuilder;
 import org.springframework.stereotype.Component;
 
 import javax.annotation.Resource;
@@ -17,23 +20,30 @@ import java.time.LocalDateTime;
 @Component
 public class MdeVisitsProducer {
 
+
     @Resource
-    private ApplicationContext applicationContext;
+    private RocketMQTemplate rocketMQTemplate;
 
 
     /**
-     * @param type       业务类型
+     * 发送记录访问消息
+     *
+     * @param type  业务类型
      * @param bizId 业务id
-     * @return void
-     * @description 发送记录访问消息
-     * @author Rayson
-     * @date 2024/5/14 下午3:31
      **/
-    public void sendVisitsSendMessage(String type, Long bizId) {
-        applicationContext.publishEvent(MdeVisitsSendMessage.builder()
-                .type(type)
+    public void send(MdeVisitsEnum type, Long bizId) {
+
+        Message<?> message = MessageBuilder.withPayload(MdeVisitsSendMessage.builder()
+                .type(type.getType())
                 .bizId(bizId)
                 .date(LocalDateTime.now())
-                .build());
+                .build()).build();
+        rocketMQTemplate.syncSend(
+                MdeVisitsSendMessage.VISITS_CLICK_TOPIC,
+                message,
+                10000,
+                // 5s
+                2
+        );
     }
 }

+ 1 - 1
menduner/menduner-system-biz/src/main/java/com/citu/module/menduner/system/service/enterprise/EnterpriseServiceImpl.java

@@ -196,7 +196,7 @@ public class EnterpriseServiceImpl implements EnterpriseService {
 
     @Override
     public void click(AppEnterpriseClickReqVO reqVO) {
-        producer.sendVisitsSendMessage(MdeVisitsEnum.ENTERPRISE_CLICK.getType(), reqVO.getId());
+        producer.send(MdeVisitsEnum.ENTERPRISE_CLICK, reqVO.getId());
     }
 
     @Override

+ 10 - 0
menduner/menduner-system-biz/src/main/java/com/citu/module/menduner/system/service/interview/InterviewInviteService.java

@@ -6,6 +6,8 @@ import com.citu.module.menduner.system.controller.app.jobhunt.interview.vo.AppIn
 import com.citu.module.menduner.system.controller.app.jobhunt.interview.vo.AppInterviewInviteRespVO;
 import com.citu.module.menduner.system.controller.app.recruit.interview.vo.*;
 import com.citu.module.menduner.system.controller.base.CommonRespVO;
+import com.citu.module.menduner.system.controller.base.analysis.RecruitAnalysisReqVO;
+import com.citu.module.menduner.system.controller.base.analysis.RecruitInterviewInviteAnalysisRespVO;
 import com.citu.module.menduner.system.controller.base.interview.InterviewInvitePageReqVO;
 import com.citu.module.menduner.system.controller.base.interview.InterviewInviteSaveReqVO;
 import com.citu.module.menduner.system.dal.dataobject.interview.InterviewInviteDO;
@@ -161,4 +163,12 @@ public interface InterviewInviteService {
      */
     void entry(Long id);
 
+    // ========== 统计分析 ==========
+
+    /** 获取待面试统计分析明细 */
+    PageResult<RecruitInterviewInviteAnalysisRespVO> getWaitInterview(RecruitAnalysisReqVO reqVO);
+
+    /** 获取完成面试统计分析明细 */
+    PageResult<RecruitInterviewInviteAnalysisRespVO> getCompleteInterview(RecruitAnalysisReqVO reqVO);
+
 }

+ 19 - 0
menduner/menduner-system-biz/src/main/java/com/citu/module/menduner/system/service/interview/InterviewInviteServiceImpl.java

@@ -10,6 +10,8 @@ import com.citu.module.menduner.system.controller.app.jobhunt.interview.vo.AppIn
 import com.citu.module.menduner.system.controller.app.jobhunt.interview.vo.AppInterviewInviteRespVO;
 import com.citu.module.menduner.system.controller.app.recruit.interview.vo.*;
 import com.citu.module.menduner.system.controller.base.CommonRespVO;
+import com.citu.module.menduner.system.controller.base.analysis.RecruitAnalysisReqVO;
+import com.citu.module.menduner.system.controller.base.analysis.RecruitInterviewInviteAnalysisRespVO;
 import com.citu.module.menduner.system.controller.base.contact.EnterpriseUserContactRespVO;
 import com.citu.module.menduner.system.controller.base.interview.InterviewInvitePageReqVO;
 import com.citu.module.menduner.system.controller.base.interview.InterviewInviteSaveReqVO;
@@ -20,6 +22,7 @@ import com.citu.module.menduner.system.dal.dataobject.job.JobCvRelDO;
 import com.citu.module.menduner.system.dal.mysql.interview.InterviewInviteMapper;
 import com.citu.module.menduner.system.dal.mysql.job.JobAdvertisedMapper;
 import com.citu.module.menduner.system.enums.cv.ConversationStatusEnum;
+import com.citu.module.menduner.system.enums.cv.JobCvRelStatusEnum;
 import com.citu.module.menduner.system.enums.interview.InterviewInviteStatusEnum;
 import com.citu.module.menduner.system.service.enterprise.bind.EnterpriseUserBindService;
 import com.citu.module.menduner.system.service.hire.HireCommissionRatioService;
@@ -31,10 +34,12 @@ import org.springframework.validation.annotation.Validated;
 import javax.annotation.Resource;
 import java.math.BigDecimal;
 import java.math.RoundingMode;
+import java.time.LocalDateTime;
 import java.util.List;
 
 import static com.citu.framework.common.exception.util.ServiceExceptionUtil.exception;
 import static com.citu.module.menduner.system.enums.ErrorCodeConstants.*;
+import static com.citu.module.menduner.system.util.RecruitAnalysisUtils.generateDateTimeRange;
 
 /**
  * 面试邀请 Service 实现类
@@ -278,6 +283,20 @@ public class InterviewInviteServiceImpl implements InterviewInviteService {
         //TODO 发送推送消息
     }
 
+    @Override
+    public PageResult<RecruitInterviewInviteAnalysisRespVO> getWaitInterview(RecruitAnalysisReqVO reqVO) {
+        LocalDateTime[] timeRange = generateDateTimeRange(reqVO);
+        return mapper.getAnalysisDetail(
+                reqVO,timeRange[0], timeRange[1], InterviewInviteStatusEnum.PENDING_INTERVIEW.getStatus());
+    }
+
+    @Override
+    public PageResult<RecruitInterviewInviteAnalysisRespVO> getCompleteInterview(RecruitAnalysisReqVO reqVO) {
+        LocalDateTime[] timeRange = generateDateTimeRange(reqVO);
+        return mapper.getAnalysisDetail(
+                reqVO,timeRange[0], timeRange[1], InterviewInviteStatusEnum.COMPLETED.getStatus());
+    }
+
     @Override
     @DSTransactional
     public void settlement(Long id) {

+ 6 - 0
menduner/menduner-system-biz/src/main/java/com/citu/module/menduner/system/service/job/JobAdvertisedService.java

@@ -10,6 +10,9 @@ import com.citu.module.menduner.system.controller.app.jobhunt.job.vo.AppJobAdver
 import com.citu.module.menduner.system.controller.app.recruit.job.vo.AppRecruitJobSaveReqVO;
 import com.citu.module.menduner.system.controller.app.recruit.job.vo.AppRecruitJobSimpleRespVO;
 import com.citu.module.menduner.system.controller.base.CommonRespVO;
+import com.citu.module.menduner.system.controller.base.analysis.RecruitAnalysisReqVO;
+import com.citu.module.menduner.system.controller.base.analysis.RecruitJobAnalysisRespVO;
+import com.citu.module.menduner.system.controller.base.analysis.RecruitJobCvRelAnalysisRespVO;
 import com.citu.module.menduner.system.controller.base.job.JobAdvertisedPageReqVO;
 import com.citu.module.menduner.system.controller.base.job.JobAdvertisedSaveReqVO;
 import com.citu.module.menduner.system.dal.dataobject.job.JobAdvertisedDO;
@@ -161,4 +164,7 @@ public interface JobAdvertisedService {
      * 置顶职位
      **/
     void top(List<Long> ids);
+
+    /** 获取发布职位浏览量统计分析明细 */
+    PageResult<RecruitJobAnalysisRespVO> getBrowseNum(RecruitAnalysisReqVO reqVO);
 }

+ 9 - 0
menduner/menduner-system-biz/src/main/java/com/citu/module/menduner/system/service/job/JobAdvertisedServiceImpl.java

@@ -15,6 +15,8 @@ import com.citu.module.menduner.system.controller.app.jobhunt.job.vo.AppJobAdver
 import com.citu.module.menduner.system.controller.app.recruit.job.vo.AppRecruitJobSaveReqVO;
 import com.citu.module.menduner.system.controller.app.recruit.job.vo.AppRecruitJobSimpleRespVO;
 import com.citu.module.menduner.system.controller.base.CommonRespVO;
+import com.citu.module.menduner.system.controller.base.analysis.RecruitAnalysisReqVO;
+import com.citu.module.menduner.system.controller.base.analysis.RecruitJobAnalysisRespVO;
 import com.citu.module.menduner.system.controller.base.contact.EnterpriseUserContactRespVO;
 import com.citu.module.menduner.system.controller.base.enterprise.vo.EnterpriseBaseSimpleRespVO;
 import com.citu.module.menduner.system.controller.base.job.JobAdvertisedPageReqVO;
@@ -24,6 +26,7 @@ import com.citu.module.menduner.system.dal.dataobject.job.JobAdvertisedDO;
 import com.citu.module.menduner.system.dal.dataobject.job.JobInterestedDO;
 import com.citu.module.menduner.system.dal.mysql.job.JobAdvertisedMapper;
 import com.citu.module.menduner.system.dal.mysql.job.JobInterestedMapper;
+import com.citu.module.menduner.system.enums.cv.JobCvRelStatusEnum;
 import com.citu.module.menduner.system.enums.job.JobStatusEnum;
 import com.citu.module.menduner.system.mq.producer.ESProducer;
 import com.citu.module.menduner.system.service.enterprise.EnterpriseService;
@@ -45,6 +48,7 @@ import java.util.stream.Collectors;
 
 import static com.citu.framework.common.exception.util.ServiceExceptionUtil.exception;
 import static com.citu.module.menduner.system.enums.ErrorCodeConstants.*;
+import static com.citu.module.menduner.system.util.RecruitAnalysisUtils.generateDateTimeRange;
 
 /**
  * 招聘职位 Service 实现类
@@ -476,4 +480,9 @@ public class JobAdvertisedServiceImpl implements JobAdvertisedService {
         }
     }
 
+    @Override
+    public PageResult<RecruitJobAnalysisRespVO> getBrowseNum(RecruitAnalysisReqVO reqVO) {
+        LocalDateTime[] timeRange = generateDateTimeRange(reqVO);
+        return jobAdvertisedMapper.getAnalysisDetail(reqVO,timeRange[0], timeRange[1]);
+    }
 }

+ 12 - 5
menduner/menduner-system-biz/src/main/java/com/citu/module/menduner/system/service/job/JobCvRelService.java

@@ -5,10 +5,11 @@ import com.citu.module.menduner.system.controller.app.jobhunt.job.hire.AppHireJo
 import com.citu.module.menduner.system.controller.app.jobhunt.job.hire.AppHireJobCvRelReqVO;
 import com.citu.module.menduner.system.controller.app.jobhunt.job.hire.AppHireJobCvRelRespVO;
 import com.citu.module.menduner.system.controller.app.jobhunt.job.vo.AppJobCvRelReqVO;
-import com.citu.module.menduner.system.controller.app.recruit.analysis.vo.AppRecruitAnalysisReqVO;
+import com.citu.module.menduner.system.controller.base.analysis.RecruitAnalysisReqVO;
 import com.citu.module.menduner.system.controller.app.recruit.person.hire.AppRecruitHireJobCvRelPageReqVO;
 import com.citu.module.menduner.system.controller.app.recruit.person.hire.AppRecruitHireJobCvRelRespVO;
 import com.citu.module.menduner.system.controller.base.CommonRespVO;
+import com.citu.module.menduner.system.controller.base.analysis.RecruitJobCvRelAnalysisRespVO;
 import com.citu.module.menduner.system.controller.base.job.JobCvRelPageReqVO;
 import com.citu.module.menduner.system.controller.base.job.JobCvRelSaveReqVO;
 import com.citu.module.menduner.system.dal.dataobject.job.JobCvRelDO;
@@ -122,17 +123,23 @@ public interface JobCvRelService {
     /**
      * 投递简历的性别比例
      **/
-    List<CommonRespVO> getJobCvSexCount(AppRecruitAnalysisReqVO reqVO);
+    List<CommonRespVO> getJobCvSexCount(RecruitAnalysisReqVO reqVO);
     /**
      * 投递简历的年龄分布
      **/
-    Map<String, Object[]> getJobCvAgeCount(AppRecruitAnalysisReqVO reqVO);
+    Map<String, Object[]> getJobCvAgeCount(RecruitAnalysisReqVO reqVO);
     /**
      * 投递简历的工作经验分布
      **/
-    Map<String, Object[]> getJobCvEduCount(AppRecruitAnalysisReqVO reqVO);
+    Map<String, Object[]> getJobCvEduCount(RecruitAnalysisReqVO reqVO);
     /**
      * 投递简历的学历分布
      **/
-    Map<String, Object[]> getJobCvExpCount(AppRecruitAnalysisReqVO reqVO);
+    Map<String, Object[]> getJobCvExpCount(RecruitAnalysisReqVO reqVO);
+
+    /** 获取新投递简历统计分析明细 */
+    PageResult<RecruitJobCvRelAnalysisRespVO> getNewCvRel(RecruitAnalysisReqVO reqVO);
+
+    /** 获取已查看简历统计分析明细 */
+    PageResult<RecruitJobCvRelAnalysisRespVO> getLookCvRel(RecruitAnalysisReqVO reqVO);
 }

+ 29 - 66
menduner/menduner-system-biz/src/main/java/com/citu/module/menduner/system/service/job/JobCvRelServiceImpl.java

@@ -9,10 +9,11 @@ import com.citu.module.menduner.system.controller.app.jobhunt.job.hire.AppHireJo
 import com.citu.module.menduner.system.controller.app.jobhunt.job.hire.AppHireJobCvRelReqVO;
 import com.citu.module.menduner.system.controller.app.jobhunt.job.hire.AppHireJobCvRelRespVO;
 import com.citu.module.menduner.system.controller.app.jobhunt.job.vo.AppJobCvRelReqVO;
-import com.citu.module.menduner.system.controller.app.recruit.analysis.vo.AppRecruitAnalysisReqVO;
 import com.citu.module.menduner.system.controller.app.recruit.person.hire.AppRecruitHireJobCvRelPageReqVO;
 import com.citu.module.menduner.system.controller.app.recruit.person.hire.AppRecruitHireJobCvRelRespVO;
 import com.citu.module.menduner.system.controller.base.CommonRespVO;
+import com.citu.module.menduner.system.controller.base.analysis.RecruitAnalysisReqVO;
+import com.citu.module.menduner.system.controller.base.analysis.RecruitJobCvRelAnalysisRespVO;
 import com.citu.module.menduner.system.controller.base.job.JobCvRelPageReqVO;
 import com.citu.module.menduner.system.controller.base.job.JobCvRelSaveReqVO;
 import com.citu.module.menduner.system.dal.dataobject.job.JobAdvertisedDO;
@@ -28,12 +29,17 @@ import org.springframework.validation.annotation.Validated;
 
 import javax.annotation.Resource;
 import java.time.LocalDateTime;
-import java.util.*;
+import java.util.Comparator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
 import java.util.stream.Collectors;
 
 import static com.citu.framework.common.exception.util.ServiceExceptionUtil.exception;
 import static com.citu.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
 import static com.citu.module.menduner.system.enums.ErrorCodeConstants.*;
+import static com.citu.module.menduner.system.util.RecruitAnalysisUtils.generateDateTimeRange;
+import static com.citu.module.menduner.system.util.RecruitAnalysisUtils.packBarCount;
 
 /**
  * 招聘职位简历投递 Service 实现类
@@ -189,13 +195,13 @@ public class JobCvRelServiceImpl implements JobCvRelService {
 
     @Override
     public PageResult<AppRecruitHireJobCvRelRespVO> page(AppRecruitHireJobCvRelPageReqVO reqVO) {
-        return jobCvRelMapper.page(reqVO,LoginUserContext.getEnterpriseId(),LoginUserContext.getUserId());
+        return jobCvRelMapper.page(reqVO, LoginUserContext.getEnterpriseId(), LoginUserContext.getUserId());
     }
 
     @Override
-    public List<CommonRespVO> getJobCvSexCount(AppRecruitAnalysisReqVO reqVO) {
+    public List<CommonRespVO> getJobCvSexCount(RecruitAnalysisReqVO reqVO) {
         LocalDateTime[] timeRange = generateDateTimeRange(reqVO);
-        List<CommonRespVO> result = jobCvRelMapper.getJobCvSexCount(timeRange[0], timeRange[1]);
+        List<CommonRespVO> result = jobCvRelMapper.getJobCvSexCount(reqVO,timeRange[0], timeRange[1]);
         for (PersonSexEnum value : PersonSexEnum.values()) {
             CommonRespVO respVO = result.stream()
                     .filter(c -> c.getKey().equals(value.getType())).findFirst().orElse(null);
@@ -213,9 +219,9 @@ public class JobCvRelServiceImpl implements JobCvRelService {
 
 
     @Override
-    public Map<String, Object[]> getJobCvAgeCount(AppRecruitAnalysisReqVO reqVO) {
+    public Map<String, Object[]> getJobCvAgeCount(RecruitAnalysisReqVO reqVO) {
         LocalDateTime[] timeRange = generateDateTimeRange(reqVO);
-        List<CommonRespVO> result = jobCvRelMapper.getJobCvAgeCount(timeRange[0], timeRange[1]);
+        List<CommonRespVO> result = jobCvRelMapper.getJobCvAgeCount(reqVO,timeRange[0], timeRange[1]);
         // 填充
         String[] ageArr = new String[]{"18-22岁", "23-30岁", "31-39岁", "40-49岁", "50-59岁", "其他年龄段"};
         for (String age : ageArr) {
@@ -237,9 +243,9 @@ public class JobCvRelServiceImpl implements JobCvRelService {
     }
 
     @Override
-    public Map<String, Object[]> getJobCvEduCount(AppRecruitAnalysisReqVO reqVO) {
+    public Map<String, Object[]> getJobCvEduCount(RecruitAnalysisReqVO reqVO) {
         LocalDateTime[] timeRange = generateDateTimeRange(reqVO);
-        List<CommonRespVO> result = jobCvRelMapper.getJobCvEduCount(timeRange[0], timeRange[1]);
+        List<CommonRespVO> result = jobCvRelMapper.getJobCvEduCount(reqVO,timeRange[0], timeRange[1]);
         // 填充
         for (EducationTypeEnum value : EducationTypeEnum.values()) {
             CommonRespVO respVO = result.stream()
@@ -255,7 +261,7 @@ public class JobCvRelServiceImpl implements JobCvRelService {
         }
         // 对 result 的 key 进行排序
         List<CommonRespVO> sortedResult = result.stream()
-                .sorted(Comparator.comparing(s->
+                .sorted(Comparator.comparing(s ->
                         EducationTypeEnum.getEnumByName(s.getKey()).getType())
                 )
                 .collect(Collectors.toList());
@@ -263,9 +269,9 @@ public class JobCvRelServiceImpl implements JobCvRelService {
     }
 
     @Override
-    public Map<String, Object[]> getJobCvExpCount(AppRecruitAnalysisReqVO reqVO) {
+    public Map<String, Object[]> getJobCvExpCount(RecruitAnalysisReqVO reqVO) {
         LocalDateTime[] timeRange = generateDateTimeRange(reqVO);
-        List<CommonRespVO> result = jobCvRelMapper.getJobCvExpCount(timeRange[0], timeRange[1]);
+        List<CommonRespVO> result = jobCvRelMapper.getJobCvExpCount(reqVO,timeRange[0], timeRange[1]);
         // 填充
         for (ExpTypeEnum value : ExpTypeEnum.values()) {
             CommonRespVO respVO = result.stream()
@@ -281,67 +287,24 @@ public class JobCvRelServiceImpl implements JobCvRelService {
         }
         // 对 result 的 key 进行排序
         List<CommonRespVO> sortedResult = result.stream()
-                .sorted(Comparator.comparing(s->
+                .sorted(Comparator.comparing(s ->
                         EducationTypeEnum.getEnumByName(s.getKey()).getType())
                 )
                 .collect(Collectors.toList());
         return packBarCount(sortedResult);
     }
 
-
-    /**
-     * 包装柱状图格式
-     **/
-    public Map<String, Object[]> packBarCount(List<CommonRespVO> result) {
-        if (CollUtil.isEmpty(result)) {
-            return null;
-        }
-
-        Map<String, Object[]> map = new LinkedHashMap<>();
-        String[] keys = result.stream()
-                .map(CommonRespVO::getKey)
-                .toArray(String[]::new);
-        map.put("x", keys);
-
-        Object[] values = result.stream()
-                .map(CommonRespVO::getValue)
-                .toArray();
-
-        map.put("y", values);
-
-        return map;
+    @Override
+    public PageResult<RecruitJobCvRelAnalysisRespVO> getNewCvRel(RecruitAnalysisReqVO reqVO) {
+        LocalDateTime[] timeRange = generateDateTimeRange(reqVO);
+        return jobCvRelMapper.getAnalysisDetail(reqVO,timeRange[0], timeRange[1],JobCvRelStatusEnum.NEW.getStatus());
     }
 
-    /**
-     * 生成时间范围
-     **/
-    public LocalDateTime[] generateDateTimeRange(AppRecruitAnalysisReqVO reqVO) {
-        if (AppRecruitAnalysisReqVO.TYPE_CUSTOM.equals(reqVO.getType())) {
-            return reqVO.getTime();
-        }
-        LocalDateTime[] dateTimeRange = new LocalDateTime[2];
-        LocalDateTime now = LocalDateTime.now();
-        switch (reqVO.getType()) {
-            case AppRecruitAnalysisReqVO.TYPE_RECENT_7_DAYS:
-                // 最新7天内
-                dateTimeRange[0] = now.minusDays(7);
-                dateTimeRange[1] = now;
-                break;
-            case AppRecruitAnalysisReqVO.TYPE_LAST_MONTH:
-                // 上个月
-                dateTimeRange[0] = now.minusMonths(1).withDayOfMonth(1);
-                dateTimeRange[1] = now.withDayOfMonth(1).minusNanos(1);
-                break;
-            case AppRecruitAnalysisReqVO.TYPE_LAST_QUARTER:
-                // 上季度
-                int currentMonth = now.getMonthValue();
-                // 计算上一季度的起始月份
-                int quarterStartMonth = ((currentMonth - 1) / 3) * 3 + 1;
-                int lastQuarterStartMonth = quarterStartMonth - 3;
-                dateTimeRange[0] = now.withMonth(lastQuarterStartMonth).withDayOfMonth(1);
-                dateTimeRange[1] = now.withMonth(quarterStartMonth).withDayOfMonth(1).minusNanos(1);
-                break;
-        }
-        return dateTimeRange;
+    @Override
+    public PageResult<RecruitJobCvRelAnalysisRespVO> getLookCvRel(RecruitAnalysisReqVO reqVO) {
+        LocalDateTime[] timeRange = generateDateTimeRange(reqVO);
+        return jobCvRelMapper.getAnalysisDetail(reqVO,timeRange[0], timeRange[1],JobCvRelStatusEnum.LOOK.getStatus());
     }
+
+
 }

+ 1 - 1
menduner/menduner-system-biz/src/main/java/com/citu/module/menduner/system/service/position/PositionServiceImpl.java

@@ -151,7 +151,7 @@ public class PositionServiceImpl implements PositionService {
 
     @Override
     public void click(AppPositionClickReqVO reqVO) {
-        producer.sendVisitsSendMessage(MdeVisitsEnum.POSITION_CLICK.getType(), reqVO.getId());
+        producer.send(MdeVisitsEnum.POSITION_CLICK, reqVO.getId());
     }
 
     @Override

+ 8 - 7
menduner/menduner-system-biz/src/main/java/com/citu/module/menduner/system/service/visits/MdeVisitsServiceImpl.java

@@ -1,15 +1,16 @@
 package com.citu.module.menduner.system.service.visits;
 
 import com.baomidou.dynamic.datasource.annotation.DSTransactional;
+import com.baomidou.dynamic.datasource.annotation.Master;
 import com.citu.framework.common.pojo.PageResult;
 import com.citu.framework.common.util.object.BeanUtils;
+import com.citu.module.menduner.common.util.LoginUserContext;
 import com.citu.module.menduner.system.controller.base.visits.MdeVisitsListReqVO;
 import com.citu.module.menduner.system.controller.base.visits.MdeVisitsPageReqVO;
 import com.citu.module.menduner.system.controller.base.visits.MdeVisitsSaveReqVO;
 import com.citu.module.menduner.system.dal.dataobject.visits.MdeVisitsDO;
 import com.citu.module.menduner.system.dal.mysql.visits.MdeVisitsMapper;
 import com.citu.module.menduner.system.mq.message.MdeVisitsSendMessage;
-import com.citu.module.menduner.common.util.LoginUserContext;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Service;
 import org.springframework.validation.annotation.Validated;
@@ -80,17 +81,18 @@ public class MdeVisitsServiceImpl implements MdeVisitsService {
     }
 
     @Override
+    @Master
     @DSTransactional // 单机+多数据源方案,使用 @DSTransactional 保证本地事务,以及数据源的切换
     public void create(MdeVisitsSendMessage reqVO) {
 
         Long userId = LoginUserContext.getUserId2();
 
         MdeVisitsDO visitsDO = mdeVisitsMapper.
-                getMdeVisitsByUserIdAndTypeAndBizIdAndDate(userId, reqVO.getType(), reqVO.getBizId(), reqVO.getDate());
+                getMdeVisitsByUserIdAndTypeAndBizIdAndDate(null==userId?0L:userId, reqVO.getType(), reqVO.getBizId(), reqVO.getDate());
         if (null == visitsDO) {
             // 新增
             MdeVisitsDO visits = new MdeVisitsDO();
-            visits.setUserId(userId);
+            visits.setUserId(null==userId?0L:userId);
             visits.setType(reqVO.getType());
             visits.setBizId(reqVO.getBizId());
             visits.setDate(reqVO.getDate());
@@ -102,17 +104,16 @@ public class MdeVisitsServiceImpl implements MdeVisitsService {
         // 增加访问量
         visitsDO.setCount(visitsDO.getCount() + 1);
         mdeVisitsMapper.updateById(visitsDO);
-
     }
 
     @Override
-    public Map<Long,Integer> getBizIdVisitsTop10List(MdeVisitsListReqVO reqVO) {
+    public Map<Long, Integer> getBizIdVisitsTop10List(MdeVisitsListReqVO reqVO) {
         List<MdeVisitsDO> list = mdeVisitsMapper.getBizIdVisitsTop10List(reqVO);
-        if(null == list) {
+        if (null == list) {
             return null;
         }
 
         return list.stream()
-                .collect(Collectors.toMap(MdeVisitsDO::getBizId, MdeVisitsDO::getCount,Integer::sum));
+                .collect(Collectors.toMap(MdeVisitsDO::getBizId, MdeVisitsDO::getCount, Integer::sum));
     }
 }

+ 72 - 0
menduner/menduner-system-biz/src/main/java/com/citu/module/menduner/system/util/RecruitAnalysisUtils.java

@@ -0,0 +1,72 @@
+package com.citu.module.menduner.system.util;
+
+import cn.hutool.core.collection.CollUtil;
+import com.citu.module.menduner.system.controller.base.CommonRespVO;
+import com.citu.module.menduner.system.controller.base.analysis.AnalysisBaseReqVO;
+
+import java.time.LocalDateTime;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 招聘分析工具类
+ **/
+public class RecruitAnalysisUtils {
+
+    /**
+     * 包装柱状图格式
+     **/
+    public static Map<String, Object[]> packBarCount(List<CommonRespVO> result) {
+        if (CollUtil.isEmpty(result)) {
+            return null;
+        }
+
+        Map<String, Object[]> map = new LinkedHashMap<>();
+        String[] keys = result.stream()
+                .map(CommonRespVO::getKey)
+                .toArray(String[]::new);
+        map.put("x", keys);
+
+        Object[] values = result.stream()
+                .map(CommonRespVO::getValue)
+                .toArray();
+
+        map.put("y", values);
+
+        return map;
+    }
+
+    /**
+     * 生成时间范围
+     **/
+    public static LocalDateTime[] generateDateTimeRange(AnalysisBaseReqVO reqVO) {
+        if (AnalysisBaseReqVO.TYPE_CUSTOM.equals(reqVO.getType())) {
+            return reqVO.getTime();
+        }
+        LocalDateTime[] dateTimeRange = new LocalDateTime[2];
+        LocalDateTime now = LocalDateTime.now();
+        switch (reqVO.getType()) {
+            case AnalysisBaseReqVO.TYPE_RECENT_7_DAYS:
+                // 最新7天内
+                dateTimeRange[0] = now.minusDays(7);
+                dateTimeRange[1] = now;
+                break;
+            case AnalysisBaseReqVO.TYPE_LAST_MONTH:
+                // 上个月
+                dateTimeRange[0] = now.minusMonths(1).withDayOfMonth(1);
+                dateTimeRange[1] = now.withDayOfMonth(1).minusNanos(1);
+                break;
+            case AnalysisBaseReqVO.TYPE_LAST_QUARTER:
+                // 上季度
+                int currentMonth = now.getMonthValue();
+                // 计算上一季度的起始月份
+                int quarterStartMonth = ((currentMonth - 1) / 3) * 3 + 1;
+                int lastQuarterStartMonth = quarterStartMonth - 3;
+                dateTimeRange[0] = now.withMonth(lastQuarterStartMonth).withDayOfMonth(1);
+                dateTimeRange[1] = now.withMonth(quarterStartMonth).withDayOfMonth(1).minusNanos(1);
+                break;
+        }
+        return dateTimeRange;
+    }
+}

+ 1 - 1
menduner/menduner-system-biz/src/main/resources/application.yaml

@@ -133,7 +133,7 @@ citu:
   db:
     # 是否开启自动切换数据源 主写从读
     transform:
-      enable: true
+      enable: false
   captcha:
     enable: false # 验证码的开关,默认为 true;
   tenant: # 多租户相关配置项