Ver código fonte

1、增加统计分析模块

rayson 11 meses atrás
pai
commit
e061ecdfba
13 arquivos alterados com 442 adições e 22 exclusões
  1. 22 9
      menduner/menduner-system-api/src/main/java/com/citu/module/menduner/system/enums/eduexp/EducationTypeEnum.java
  2. 17 0
      menduner/menduner-system-api/src/main/java/com/citu/module/menduner/system/enums/person/PersonSexEnum.java
  3. 23 1
      menduner/menduner-system-api/src/main/java/com/citu/module/menduner/system/enums/workexp/ExpTypeEnum.java
  4. 62 0
      menduner/menduner-system-biz/src/main/java/com/citu/module/menduner/system/controller/appadmin/analysis/AppAdminAnalysisController.java
  5. 26 0
      menduner/menduner-system-biz/src/main/java/com/citu/module/menduner/system/controller/appadmin/analysis/vo/AppAdminAnalysisReqVO.java
  6. 9 2
      menduner/menduner-system-biz/src/main/java/com/citu/module/menduner/system/dal/mysql/enterprise/EnterpriseMapper.java
  7. 3 1
      menduner/menduner-system-biz/src/main/java/com/citu/module/menduner/system/dal/mysql/industry/IndustryMapper.java
  8. 80 0
      menduner/menduner-system-biz/src/main/java/com/citu/module/menduner/system/dal/mysql/job/JobCvRelMapper.java
  9. 2 0
      menduner/menduner-system-biz/src/main/java/com/citu/module/menduner/system/dal/mysql/position/PositionMapper.java
  10. 15 1
      menduner/menduner-system-biz/src/main/java/com/citu/module/menduner/system/dal/mysql/school/SchoolMapper.java
  11. 2 1
      menduner/menduner-system-biz/src/main/java/com/citu/module/menduner/system/service/enterprise/bind/EnterpriseUserBindServiceImpl.java
  12. 20 0
      menduner/menduner-system-biz/src/main/java/com/citu/module/menduner/system/service/job/JobCvRelService.java
  13. 161 7
      menduner/menduner-system-biz/src/main/java/com/citu/module/menduner/system/service/job/JobCvRelServiceImpl.java

+ 22 - 9
menduner/menduner-system-api/src/main/java/com/citu/module/menduner/system/enums/eduexp/EducationTypeEnum.java

@@ -11,17 +11,30 @@ import lombok.Getter;
 public enum EducationTypeEnum {
 
 
-    PRIMARY_SCHOOL(0),
-    JUNIOR_HIGH_SCHOOL(1),
-    HIGH_SCHOOL(2),
-    COLLEGE(3),
-    BACHELOR(4),
-    MASTER(5),
-    DOCTOR(6),
-    OTHER(99);
+    PRIMARY_SCHOOL("0","初中及以下"),
+    JUNIOR_HIGH_SCHOOL("1","中专/中技"),
+    HIGH_SCHOOL("2","高中"),
+    COLLEGE("3","大专"),
+    BACHELOR("4","本科"),
+    MASTER("5","硕士"),
+    DOCTOR("6","博士"),
+    OTHER("99","其他");
 
     /**
      * 类型
      */
-    private final Integer type;
+    private final String type;
+
+    private final String name;
+
+    // 根据name获取枚举
+    public static EducationTypeEnum getEnumByName(String name) {
+        for (EducationTypeEnum educationTypeEnum : EducationTypeEnum.values()) {
+            if (educationTypeEnum.getName().equals(name)) {
+                return educationTypeEnum;
+            }
+        }
+        return PRIMARY_SCHOOL;
+    }
+
 }

+ 17 - 0
menduner/menduner-system-api/src/main/java/com/citu/module/menduner/system/enums/person/PersonSexEnum.java

@@ -0,0 +1,17 @@
+package com.citu.module.menduner.system.enums.person;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * 人才性别(0未知 | 1男 | 2女)
+ **/
+@Getter
+@AllArgsConstructor
+public enum PersonSexEnum {
+    UNKNOWN("0", "未知"),
+    MALE("1", "男"),
+    FEMALE("2", "女");
+    private final String type;
+    private final String name;
+}

+ 23 - 1
menduner/menduner-system-api/src/main/java/com/citu/module/menduner/system/enums/workexp/ExpTypeEnum.java

@@ -1,5 +1,6 @@
 package com.citu.module.menduner.system.enums.workexp;
 
+import com.citu.module.menduner.system.enums.eduexp.EducationTypeEnum;
 import lombok.AllArgsConstructor;
 import lombok.Getter;
 
@@ -8,6 +9,27 @@ import lombok.Getter;
  **/
 @Getter
 @AllArgsConstructor
-public class ExpTypeEnum {
+public enum ExpTypeEnum {
+    IN_SCHOOL("0","在校生"),
+    NEW_GRADUATE("1","应届生"),
+    NO_LIMIT("2","经验不限"),
+    LESS_THAN_ONE_YEAR("3","1年以内"),
+    ONE_TO_THREE_YEARS("4","1-3年"),
+    THREE_TO_FIVE_YEARS("5","3-5年"),
+    FIVE_TO_TEN_YEARS("6","5-10年"),
+    MORE_THAN_TEN_YEARS("7","10年以上");
 
+    private final String type;
+
+    private final String name;
+
+    // 根据name获取枚举
+    public static ExpTypeEnum getEnumByName(String name) {
+        for (ExpTypeEnum enumEnum : ExpTypeEnum.values()) {
+            if (enumEnum.getName().equals(name)) {
+                return enumEnum;
+            }
+        }
+        return IN_SCHOOL;
+    }
 }

+ 62 - 0
menduner/menduner-system-biz/src/main/java/com/citu/module/menduner/system/controller/appadmin/analysis/AppAdminAnalysisController.java

@@ -0,0 +1,62 @@
+package com.citu.module.menduner.system.controller.appadmin.analysis;
+
+import com.citu.framework.common.pojo.CommonResult;
+import com.citu.framework.security.core.annotations.PreAuthenticated;
+import com.citu.module.menduner.system.controller.appadmin.analysis.vo.AppAdminAnalysisReqVO;
+import com.citu.module.menduner.system.controller.base.CommonRespVO;
+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.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 AppAdminAnalysisController {
+
+    @Resource
+    private JobCvRelService jobCvcRelService;
+
+    @GetMapping("/get/job/cv/sex/count")
+    @Operation(summary = "获取投递简历的性别分布")
+    @PreAuthenticated
+    public CommonResult<List<CommonRespVO>> getJobCvSexCount(@Valid AppAdminAnalysisReqVO reqVO) {
+        return success(jobCvcRelService.getJobCvSexCount(reqVO));
+    }
+
+    @GetMapping("/get/job/cv/age/count")
+    @Operation(summary = "获取投递简历的年龄分布")
+    @PreAuthenticated
+    public CommonResult<Map<String, Object[]>> getJobCvAgeCount(@Valid AppAdminAnalysisReqVO reqVO) {
+        return success(jobCvcRelService.getJobCvAgeCount(reqVO));
+    }
+
+    @GetMapping("/get/job/cv/edu/count")
+    @Operation(summary = "获取投递简历的学历分布")
+    @PreAuthenticated
+    public CommonResult<Map<String, Object[]>> getJobCvEduCount(@Valid AppAdminAnalysisReqVO reqVO) {
+        return success(jobCvcRelService.getJobCvEduCount(reqVO));
+    }
+
+    @GetMapping("/get/job/cv/exp/count")
+    @Operation(summary = "获取投递简历的工作经验分布")
+    @PreAuthenticated
+    public CommonResult<Map<String, Object[]>> getJobCvExpCount(@Valid AppAdminAnalysisReqVO reqVO) {
+        return success(jobCvcRelService.getJobCvExpCount(reqVO));
+    }
+
+
+}

+ 26 - 0
menduner/menduner-system-biz/src/main/java/com/citu/module/menduner/system/controller/appadmin/analysis/vo/AppAdminAnalysisReqVO.java

@@ -0,0 +1,26 @@
+package com.citu.module.menduner.system.controller.appadmin.analysis.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
+
+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")
+@Data
+public class AppAdminAnalysisReqVO {
+
+    public static final String TYPE_RECENT_7_DAYS = "0";
+    public static final String TYPE_LAST_MONTH = "1";
+    public static final String TYPE_LAST_QUARTER = "2";
+    public static final String TYPE_CUSTOM = "99";
+
+    @Schema(description = "统计类型 0最近7天|1上个月|2上季度|99自定义",required = true)
+    private String type;
+
+    @Schema(description = "自定义时间范围")
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    private LocalDateTime[] time;
+}

+ 9 - 2
menduner/menduner-system-biz/src/main/java/com/citu/module/menduner/system/dal/mysql/enterprise/EnterpriseMapper.java

@@ -6,8 +6,8 @@ import com.citu.framework.mybatis.core.mapper.BaseMapperX;
 import com.citu.framework.mybatis.core.query.LambdaQueryWrapperX;
 import com.citu.framework.mybatis.core.query.MPJLambdaWrapperX;
 import com.citu.module.menduner.system.controller.app.enterprise.vo.AppEnterpriseSearchPageReqVO;
-import com.citu.module.menduner.system.controller.base.enterprise.vo.EnterpriseBaseSimpleRespVO;
 import com.citu.module.menduner.system.controller.base.CommonRespVO;
+import com.citu.module.menduner.system.controller.base.enterprise.vo.EnterpriseBaseSimpleRespVO;
 import com.citu.module.menduner.system.controller.base.enterprise.vo.EnterpriseListReqVO;
 import com.citu.module.menduner.system.controller.base.enterprise.vo.EnterprisePageReqVO;
 import com.citu.module.menduner.system.dal.dataobject.enterprise.EnterpriseBusinessDO;
@@ -81,7 +81,14 @@ public interface EnterpriseMapper extends BaseMapperX<EnterpriseDO> {
         return selectList(EnterpriseDO::getParentId, parentIds);
     }
 
-    List<CommonRespVO> searchByName(String name);
+    default List<CommonRespVO> searchByName(String name) {
+        MPJLambdaWrapperX<EnterpriseDO> wrapper = new MPJLambdaWrapperX<>();
+        wrapper.selectAs(EnterpriseDO::getId, "`key`");
+        wrapper.selectAs(EnterpriseDO::getName, CommonRespVO::getValue);
+        wrapper.like(EnterpriseDO::getName, name);
+        wrapper.eq(EnterpriseDO::getStatus, MendunerStatusEnum.ENABLE.getStatus());
+        return selectJoinList(CommonRespVO.class, wrapper);
+    }
 
 
     default EnterpriseDO selectListById(Long id) {

+ 3 - 1
menduner/menduner-system-biz/src/main/java/com/citu/module/menduner/system/dal/mysql/industry/IndustryMapper.java

@@ -3,11 +3,12 @@ package com.citu.module.menduner.system.dal.mysql.industry;
 import com.citu.framework.common.pojo.PageResult;
 import com.citu.framework.mybatis.core.mapper.BaseMapperX;
 import com.citu.framework.mybatis.core.query.LambdaQueryWrapperX;
+import com.citu.module.menduner.system.controller.app.industry.vo.AppIndustryListReqVO;
 import com.citu.module.menduner.system.controller.base.industry.IndustryListReqVO;
 import com.citu.module.menduner.system.controller.base.industry.IndustryPageReqVO;
-import com.citu.module.menduner.system.controller.app.industry.vo.AppIndustryListReqVO;
 import com.citu.module.menduner.system.dal.dataobject.industry.IndustryDO;
 import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Update;
 
 import java.util.Collection;
 import java.util.List;
@@ -52,6 +53,7 @@ public interface IndustryMapper extends BaseMapperX<IndustryDO> {
     /**
      * 清空行业数据
      **/
+    @Update("TRUNCATE TABLE mde_industry")
     Integer truncate();
 
 }

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

@@ -1,5 +1,6 @@
 package com.citu.module.menduner.system.dal.mysql.job;
 
+import cn.hutool.core.collection.CollUtil;
 import com.citu.framework.common.pojo.PageParam;
 import com.citu.framework.common.pojo.PageResult;
 import com.citu.framework.mybatis.core.mapper.BaseMapperX;
@@ -11,6 +12,7 @@ import com.citu.module.menduner.system.controller.appadmin.person.cv.AppAdminJob
 import com.citu.module.menduner.system.controller.appadmin.person.cv.AppAdminJobCvRelRespVO;
 import com.citu.module.menduner.system.controller.appadmin.person.hire.AppAdminHireJobCvRelPageReqVO;
 import com.citu.module.menduner.system.controller.appadmin.person.hire.AppAdminHireJobCvRelRespVO;
+import com.citu.module.menduner.system.controller.base.CommonRespVO;
 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.job.JobAdvertisedDO;
@@ -23,7 +25,10 @@ import com.citu.module.menduner.system.enums.unfit.UnfitTypeEnum;
 import org.apache.ibatis.annotations.Mapper;
 
 import java.time.LocalDateTime;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
 import java.util.List;
+import java.util.Map;
 
 /**
  * 招聘职位简历投递 Mapper
@@ -196,4 +201,79 @@ public interface JobCvRelMapper extends BaseMapperX<JobCvRelDO> {
         return selectJoinPage(pageParam, JobCvRelDO.class, wrapper);
     }
 
+    // ========== 统计 ==========
+
+    /**
+     * 投递简历的性别比例
+     **/
+    default List<CommonRespVO> getJobCvSexCount(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.groupBy(PersonInfoDO::getSex);
+        wrapper.orderByDesc("`key`");
+        return selectJoinList(CommonRespVO.class, wrapper);
+    }
+
+
+
+    /**
+     * 投递简历的年龄分布
+     **/
+    default List<CommonRespVO> getJobCvAgeCount(LocalDateTime startTime, LocalDateTime endTime) {
+        MPJLambdaWrapperX<JobCvRelDO> wrapper = new MPJLambdaWrapperX<>();
+
+        String sql = "CASE \n" +
+                "        WHEN YEAR(CURDATE()) - YEAR(birthday) BETWEEN 18 AND 22 THEN '18-22岁'\n" +
+                "        WHEN YEAR(CURDATE()) - YEAR(birthday) BETWEEN 23 AND 30 THEN '23-30岁'\n" +
+                "        WHEN YEAR(CURDATE()) - YEAR(birthday) BETWEEN 31 AND 39 THEN '31-39岁'\n" +
+                "        WHEN YEAR(CURDATE()) - YEAR(birthday) BETWEEN 40 AND 49 THEN '40-49岁'\n" +
+                "        WHEN YEAR(CURDATE()) - YEAR(birthday) BETWEEN 50 AND 59 THEN '50-59岁'\n" +
+                "        ELSE '其他年龄段'\n" +
+                "    END";
+        wrapper.selectFunc(() -> sql, PersonInfoDO::getBirthday, "`key`");
+        wrapper.selectCount(JobCvRelDO::getId, CommonRespVO::getValue);
+
+
+        wrapper.innerJoin(PersonInfoDO.class, PersonInfoDO::getUserId, JobCvRelDO::getUserId);
+        wrapper.between(JobCvRelDO::getCreateTime, startTime, endTime);
+        wrapper.groupBy("`key`");
+        wrapper.orderByDesc("`key`");
+        return selectJoinList(CommonRespVO.class, wrapper);
+    }
+
+    /**
+     * 投递简历的工作经验分布
+     **/
+    default List<CommonRespVO> getJobCvExpCount(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.groupBy(PersonInfoDO::getExpType);
+        wrapper.orderByDesc("`key`");
+        return selectJoinList(CommonRespVO.class, wrapper);
+    }
+
+    /**
+     * 投递简历的学历分布
+     **/
+    default List<CommonRespVO> getJobCvEduCount(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.groupBy(PersonInfoDO::getEduType);
+        wrapper.orderByDesc("`key`");
+
+        return selectJoinList(CommonRespVO.class, wrapper);
+    }
+
+
 }

+ 2 - 0
menduner/menduner-system-biz/src/main/java/com/citu/module/menduner/system/dal/mysql/position/PositionMapper.java

@@ -9,6 +9,7 @@ import com.citu.module.menduner.system.controller.app.position.vo.AppPositionLis
 import com.citu.module.menduner.system.dal.dataobject.position.PositionDO;
 import org.apache.ibatis.annotations.Mapper;
 import org.apache.ibatis.annotations.Select;
+import org.apache.ibatis.annotations.Update;
 
 import java.util.Collection;
 import java.util.List;
@@ -62,6 +63,7 @@ public interface PositionMapper extends BaseMapperX<PositionDO> {
     /**
      * 清空职位数据
      **/
+    @Update("TRUNCATE TABLE mde_position")
     Integer truncate();
 
     /**

+ 15 - 1
menduner/menduner-system-biz/src/main/java/com/citu/module/menduner/system/dal/mysql/school/SchoolMapper.java

@@ -3,10 +3,15 @@ package com.citu.module.menduner.system.dal.mysql.school;
 import com.citu.framework.common.pojo.PageResult;
 import com.citu.framework.mybatis.core.query.LambdaQueryWrapperX;
 import com.citu.framework.mybatis.core.mapper.BaseMapperX;
+import com.citu.framework.mybatis.core.query.MPJLambdaWrapperX;
 import com.citu.module.menduner.system.controller.base.school.SchoolPageReqVO;
 import com.citu.module.menduner.system.controller.base.CommonRespVO;
+import com.citu.module.menduner.system.dal.dataobject.job.JobCvRelDO;
+import com.citu.module.menduner.system.dal.dataobject.person.PersonInfoDO;
 import com.citu.module.menduner.system.dal.dataobject.school.SchoolDO;
+import com.citu.module.menduner.system.enums.MendunerStatusEnum;
 import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Update;
 
 import java.util.List;
 
@@ -34,7 +39,16 @@ public interface SchoolMapper extends BaseMapperX<SchoolDO> {
     /**
      * 清空职位数据
      **/
+    @Update("TRUNCATE TABLE mde_school")
     Integer truncate();
 
-    List<CommonRespVO> searchByName(String name);
+
+   default List<CommonRespVO> searchByName(String name){
+       MPJLambdaWrapperX<SchoolDO> wrapper = new MPJLambdaWrapperX<>();
+       wrapper.selectAs(SchoolDO::getId, "`key`");
+       wrapper.selectAs(SchoolDO::getName, CommonRespVO::getValue);
+       wrapper.like(SchoolDO::getName, name);
+       wrapper.eq(SchoolDO::getStatus, MendunerStatusEnum.ENABLE.getStatus());
+       return selectJoinList(CommonRespVO.class, wrapper);
+   }
 }

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

@@ -325,7 +325,8 @@ public class EnterpriseUserBindServiceImpl implements EnterpriseUserBindService
         if (null == userBindDO) {
             throw exception(MDE_ENTERPRISE_USER_BIND_NOT_EXISTS);
         }
-        if (userBindDO.getPostId().equals(postId)) {
+        if (null != userBindDO.getPostId() &&
+                userBindDO.getPostId().equals(postId)) {
             return true;
         }
         userBindDO.setPostId(postId);

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

@@ -5,6 +5,7 @@ import com.citu.module.menduner.system.controller.app.job.hire.AppHireJobCvRelQu
 import com.citu.module.menduner.system.controller.app.job.hire.AppHireJobCvRelReqVO;
 import com.citu.module.menduner.system.controller.app.job.hire.AppHireJobCvRelRespVO;
 import com.citu.module.menduner.system.controller.app.job.vo.AppJobCvRelReqVO;
+import com.citu.module.menduner.system.controller.appadmin.analysis.vo.AppAdminAnalysisReqVO;
 import com.citu.module.menduner.system.controller.appadmin.person.cv.AppAdminJobCvRelInviteReqVO;
 import com.citu.module.menduner.system.controller.appadmin.person.hire.AppAdminHireJobCvRelPageReqVO;
 import com.citu.module.menduner.system.controller.appadmin.person.hire.AppAdminHireJobCvRelRespVO;
@@ -15,6 +16,7 @@ import com.citu.module.menduner.system.dal.dataobject.job.JobCvRelDO;
 
 import javax.validation.Valid;
 import java.util.List;
+import java.util.Map;
 
 /**
  * 招聘职位简历投递 Service 接口
@@ -121,4 +123,22 @@ public interface JobCvRelService {
      * @return PageResult<AppAdminHireJobCvRelRespVO>
      **/
     PageResult<AppAdminHireJobCvRelRespVO> page(AppAdminHireJobCvRelPageReqVO reqVO);
+
+    // ========== 统计分析 ==========
+    /**
+     * 投递简历的性别比例
+     **/
+    List<CommonRespVO> getJobCvSexCount(AppAdminAnalysisReqVO reqVO);
+    /**
+     * 投递简历的年龄分布
+     **/
+    Map<String, Object[]> getJobCvAgeCount(AppAdminAnalysisReqVO reqVO);
+    /**
+     * 投递简历的工作经验分布
+     **/
+    Map<String, Object[]> getJobCvEduCount(AppAdminAnalysisReqVO reqVO);
+    /**
+     * 投递简历的学历分布
+     **/
+    Map<String, Object[]> getJobCvExpCount(AppAdminAnalysisReqVO reqVO);
 }

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

@@ -1,5 +1,6 @@
 package com.citu.module.menduner.system.service.job;
 
+import cn.hutool.core.collection.CollUtil;
 import com.baomidou.dynamic.datasource.annotation.DSTransactional;
 import com.citu.framework.common.pojo.PageResult;
 import com.citu.framework.common.util.object.BeanUtils;
@@ -8,7 +9,7 @@ import com.citu.module.menduner.system.controller.app.job.hire.AppHireJobCvRelQu
 import com.citu.module.menduner.system.controller.app.job.hire.AppHireJobCvRelReqVO;
 import com.citu.module.menduner.system.controller.app.job.hire.AppHireJobCvRelRespVO;
 import com.citu.module.menduner.system.controller.app.job.vo.AppJobCvRelReqVO;
-import com.citu.module.menduner.system.controller.appadmin.person.cv.AppAdminJobCvRelInviteReqVO;
+import com.citu.module.menduner.system.controller.appadmin.analysis.vo.AppAdminAnalysisReqVO;
 import com.citu.module.menduner.system.controller.appadmin.person.hire.AppAdminHireJobCvRelPageReqVO;
 import com.citu.module.menduner.system.controller.appadmin.person.hire.AppAdminHireJobCvRelRespVO;
 import com.citu.module.menduner.system.controller.base.CommonRespVO;
@@ -16,18 +17,18 @@ 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;
 import com.citu.module.menduner.system.dal.dataobject.job.JobCvRelDO;
-import com.citu.module.menduner.system.dal.mysql.job.JobAdvertisedMapper;
 import com.citu.module.menduner.system.dal.mysql.job.JobCvRelMapper;
 import com.citu.module.menduner.system.enums.MendunerStatusEnum;
 import com.citu.module.menduner.system.enums.cv.JobCvRelStatusEnum;
-import com.citu.module.menduner.system.service.interview.InterviewInviteService;
+import com.citu.module.menduner.system.enums.eduexp.EducationTypeEnum;
+import com.citu.module.menduner.system.enums.person.PersonSexEnum;
+import com.citu.module.menduner.system.enums.workexp.ExpTypeEnum;
 import org.springframework.stereotype.Service;
 import org.springframework.validation.annotation.Validated;
 
 import javax.annotation.Resource;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
+import java.time.LocalDateTime;
+import java.util.*;
 import java.util.stream.Collectors;
 
 import static com.citu.framework.common.exception.util.ServiceExceptionUtil.exception;
@@ -191,7 +192,7 @@ public class JobCvRelServiceImpl implements JobCvRelService {
 
     @Override
     public PageResult<AppHireJobCvRelRespVO> page(AppHireJobCvRelQueryReqVO reqVO) {
-        return jobCvRelMapper.page(reqVO,LoginUserContext.getUserId());
+        return jobCvRelMapper.page(reqVO, LoginUserContext.getUserId());
     }
 
     @Override
@@ -209,4 +210,157 @@ public class JobCvRelServiceImpl implements JobCvRelService {
     public PageResult<AppAdminHireJobCvRelRespVO> page(AppAdminHireJobCvRelPageReqVO reqVO) {
         return jobCvRelMapper.page(reqVO);
     }
+
+    @Override
+    public List<CommonRespVO> getJobCvSexCount(AppAdminAnalysisReqVO reqVO) {
+        LocalDateTime[] timeRange = generateDateTimeRange(reqVO);
+        List<CommonRespVO> result = jobCvRelMapper.getJobCvSexCount(timeRange[0], timeRange[1]);
+        for (PersonSexEnum value : PersonSexEnum.values()) {
+            CommonRespVO respVO = result.stream()
+                    .filter(c -> c.getKey().equals(value.getType())).findFirst().orElse(null);
+            if (null == respVO) {
+                CommonRespVO newResp = new CommonRespVO();
+                newResp.setKey(value.getName());
+                newResp.setValue(0L);
+                result.add(newResp);
+            } else {
+                respVO.setKey(value.getName());
+            }
+        }
+        return result;
+    }
+
+
+    @Override
+    public Map<String, Object[]> getJobCvAgeCount(AppAdminAnalysisReqVO reqVO) {
+        LocalDateTime[] timeRange = generateDateTimeRange(reqVO);
+        List<CommonRespVO> result = jobCvRelMapper.getJobCvAgeCount(timeRange[0], timeRange[1]);
+        // 填充
+        String[] ageArr = new String[]{"18-22岁", "23-30岁", "31-39岁", "40-49岁", "50-59岁", "其他年龄段"};
+        for (String age : ageArr) {
+            CommonRespVO respVO = result.stream()
+                    .filter(c -> c.getKey().equals(age)).findFirst().orElse(null);
+            if (null == respVO) {
+                CommonRespVO newResp = new CommonRespVO();
+                newResp.setKey(age);
+                newResp.setValue(0L);
+                result.add(newResp);
+            }
+        }
+        // 对 result 的 key 进行排序
+        List<CommonRespVO> sortedResult = result.stream()
+                .sorted(Comparator.comparing(CommonRespVO::getKey))
+                .collect(Collectors.toList());
+        // 对result的key进行排序
+        return packBarCount(sortedResult);
+    }
+
+    @Override
+    public Map<String, Object[]> getJobCvEduCount(AppAdminAnalysisReqVO reqVO) {
+        LocalDateTime[] timeRange = generateDateTimeRange(reqVO);
+        List<CommonRespVO> result = jobCvRelMapper.getJobCvEduCount(timeRange[0], timeRange[1]);
+        // 填充
+        for (EducationTypeEnum value : EducationTypeEnum.values()) {
+            CommonRespVO respVO = result.stream()
+                    .filter(c -> c.getKey().equals(value.getType())).findFirst().orElse(null);
+            if (null == respVO) {
+                CommonRespVO newResp = new CommonRespVO();
+                newResp.setKey(value.getName());
+                newResp.setValue(0L);
+                result.add(newResp);
+            } else {
+                respVO.setKey(value.getName());
+            }
+        }
+        // 对 result 的 key 进行排序
+        List<CommonRespVO> sortedResult = result.stream()
+                .sorted(Comparator.comparing(s->
+                        EducationTypeEnum.getEnumByName(s.getKey()).getType())
+                )
+                .collect(Collectors.toList());
+        return packBarCount(sortedResult);
+    }
+
+    @Override
+    public Map<String, Object[]> getJobCvExpCount(AppAdminAnalysisReqVO reqVO) {
+        LocalDateTime[] timeRange = generateDateTimeRange(reqVO);
+        List<CommonRespVO> result = jobCvRelMapper.getJobCvExpCount(timeRange[0], timeRange[1]);
+        // 填充
+        for (ExpTypeEnum value : ExpTypeEnum.values()) {
+            CommonRespVO respVO = result.stream()
+                    .filter(c -> c.getKey().equals(value.getType())).findFirst().orElse(null);
+            if (null == respVO) {
+                CommonRespVO newResp = new CommonRespVO();
+                newResp.setKey(value.getName());
+                newResp.setValue(0L);
+                result.add(newResp);
+            } else {
+                respVO.setKey(value.getName());
+            }
+        }
+        // 对 result 的 key 进行排序
+        List<CommonRespVO> sortedResult = result.stream()
+                .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;
+    }
+
+    /**
+     * 生成时间范围
+     **/
+    public LocalDateTime[] generateDateTimeRange(AppAdminAnalysisReqVO reqVO) {
+        if (AppAdminAnalysisReqVO.TYPE_CUSTOM.equals(reqVO.getType())) {
+            return reqVO.getTime();
+        }
+        LocalDateTime[] dateTimeRange = new LocalDateTime[2];
+        LocalDateTime now = LocalDateTime.now();
+        switch (reqVO.getType()) {
+            case AppAdminAnalysisReqVO.TYPE_RECENT_7_DAYS:
+                // 最新7天内
+                dateTimeRange[0] = now.minusDays(7);
+                dateTimeRange[1] = now;
+                break;
+            case AppAdminAnalysisReqVO.TYPE_LAST_MONTH:
+                // 上个月
+                dateTimeRange[0] = now.minusMonths(1).withDayOfMonth(1);
+                dateTimeRange[1] = now.withDayOfMonth(1).minusNanos(1);
+                break;
+            case AppAdminAnalysisReqVO.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;
+    }
 }