添加功能

This commit is contained in:
马宝龙
2026-06-26 20:59:07 +08:00
parent 6b575480ce
commit fd834d3647
9 changed files with 619 additions and 0 deletions

View File

@@ -0,0 +1,112 @@
package com.ruoyi.cms.controller;
import com.ruoyi.cms.domain.dto.QueryParamDto;
import com.ruoyi.cms.service.AnalysisJobDemandTreadService;
import com.ruoyi.common.core.domain.AjaxResult;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 岗位需求趋势变化分析
*
* @author 马宝龙
* @date 2026/6/26
*/
@RestController
@RequestMapping("/analysis/jobDemandTread")
@RequiredArgsConstructor
public class AnalysisJobDemandTreadController {
private final AnalysisJobDemandTreadService analysisJobDemandTreadService;
/**
* 数据总览
*
* @param dto 查询参数
* @return 数据总览
*/
@PostMapping("/overview")
public AjaxResult overview(@RequestBody QueryParamDto dto) {
return AjaxResult.success(analysisJobDemandTreadService.overview(dto));
}
/**
* 宏观经济与岗位需求关联
*
* @param dto 查询参数
* @return 结果列表
*/
@PostMapping("/economyAndJobDemandCorrelation")
public AjaxResult economyAndJobDemandCorrelation(@RequestBody QueryParamDto dto) {
return AjaxResult.success(analysisJobDemandTreadService.economyAndJobDemandCorrelation(dto));
}
/**
* 热门岗位Top10排名
*
* @param dto 查询参数
* @return 结果列表
*/
@PostMapping("/hotJobRank")
public AjaxResult hotJobRank(@RequestBody QueryParamDto dto) {
return AjaxResult.success(analysisJobDemandTreadService.hotJobRank(dto));
}
/**
* GDP与岗位需求相关性分析
*
* @param dto 查询参数
* @return 结果列表
*/
@PostMapping("/gdpAndJobDemandCorrelation")
public AjaxResult gdpAndJobDemandCorrelation(@RequestBody QueryParamDto dto) {
return AjaxResult.success(analysisJobDemandTreadService.gdpAndJobDemandCorrelation(dto));
}
/**
* 岗位类型占比变化趋势
*
* @param dto 查询参数
* @return 趋势数据
*/
@PostMapping("/jobTypePercentageTread")
public AjaxResult jobTypePercentageTread(@RequestBody QueryParamDto dto) {
return AjaxResult.success(analysisJobDemandTreadService.jobTypePercentageTread(dto));
}
/**
* 岗位需求总量
*
* @param dto 查询参数
* @return 趋势数据
*/
@PostMapping("/jobDemandCountTread")
public AjaxResult jobDemandCountTread(@RequestBody QueryParamDto dto) {
return AjaxResult.success(analysisJobDemandTreadService.jobDemandCountTread(dto));
}
/**
* 查询职业列表
*
* @return 职业列表
*/
@GetMapping("/occupationList")
public AjaxResult occupationList() {
return AjaxResult.success(analysisJobDemandTreadService.occupationList());
}
/**
* 技能关键词
*
* @param dto 查询参数
* @return 结果列表
*/
@PostMapping("/skillKeyword")
public AjaxResult skillKeyword(@RequestBody QueryParamDto dto) {
return AjaxResult.success(analysisJobDemandTreadService.skillKeyword(dto));
}
}

View File

@@ -54,6 +54,10 @@ public class QueryParamDto implements Serializable {
* 高校类型
*/
private String universityType;
/**
* 职业
*/
private String occupation;
/**
* 开始时间
*/

View File

@@ -0,0 +1,47 @@
package com.ruoyi.cms.domain.vo;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.math.BigDecimal;
/**
* 岗位需求趋势变化分析 - 岗位需求总量
*
* @author 马宝龙
* @date 2026/6/25
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class JobDemandTreadDemandVo implements Serializable {
private static final long serialVersionUID = -8380229611694077625L;
/**
* 编码
*/
private String code;
/**
* 描述
*/
private String desc;
/**
* 岗位需求
*/
private Long jobDemandCount;
/**
* 求职者
*/
private Long lobarSupplyCount;
/**
* 求人倍率
*/
private BigDecimal demandSupplyRate;
/**
* 求人倍率环比
*/
private BigDecimal demandSupplyRateMom;
}

View File

@@ -0,0 +1,47 @@
package com.ruoyi.cms.domain.vo;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.math.BigDecimal;
/**
* 岗位需求趋势变化分析 - 宏观经济与岗位需求关联
*
* @author 马宝龙
* @date 2026/6/25
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class JobDemandTreadEconomyCorrelationVo implements Serializable {
private static final long serialVersionUID = -8380229611694077625L;
/**
* 编码
*/
private String code;
/**
* 描述
*/
private String desc;
/**
* GDP增速
*/
private BigDecimal gdpGrowthRate;
/**
* CPI同比
*/
private BigDecimal cpiYoyRate;
/**
* PMI指数
*/
private BigDecimal pmiIndex;
/**
* 岗位需求
*/
private Long jobDemandCount;
}

View File

@@ -0,0 +1,32 @@
package com.ruoyi.cms.domain.vo;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.math.BigDecimal;
/**
* 岗位需求趋势变化分析 - GDP与岗位需求相关性分析
*
* @author 马宝龙
* @date 2026/6/25
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class JobDemandTreadGDPCorrelationVo implements Serializable {
private static final long serialVersionUID = -2297176575382876671L;
/**
* GDP指数
*/
private BigDecimal gdpIndex;
/**
* 岗位需求
*/
private Long jobDemandCount;
}

View File

@@ -0,0 +1,56 @@
package com.ruoyi.cms.domain.vo;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.math.BigDecimal;
/**
* 岗位需求趋势变化分析 - 数据总览
*
* @author 马宝龙
* @date 2026/6/25
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class JobDemandTreadOverviewVo implements Serializable {
private static final long serialVersionUID = -7539147768207113373L;
/**
* 岗位需求总量
*/
private Long jobDemandCount;
/**
* 岗位需求总量环比
*/
private BigDecimal jobDemandCountMom;
/**
* 求人倍率
*/
private BigDecimal demandSupplyRate;
/**
* 求人倍率环比
*/
private BigDecimal demandSupplyRateMom;
/**
* 技术类岗位占比
*/
private BigDecimal technicalJobPercentage;
/**
* 技术类岗位占比环比
*/
private BigDecimal technicalJobPercentageMom;
/**
* 硬技能需求人数
*/
private Long hardSkillDemandCount;
/**
* 硬技能需求人数环比
*/
private BigDecimal hardSkillDemandCountMom;
}

View File

@@ -0,0 +1,35 @@
package com.ruoyi.cms.domain.vo;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
/**
* 技能关键字
*
* @author 马宝龙
* @date 2026/6/25
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class SkillKeywordVo implements Serializable {
private static final long serialVersionUID = 875430729680133136L;
/**
* 关键词
*/
private String keyword;
/**
* 类型
*/
private String type;
/**
* 出现次数
*/
private Long count;
}

View File

@@ -0,0 +1,86 @@
package com.ruoyi.cms.service;
import com.ruoyi.cms.domain.dto.QueryParamDto;
import com.ruoyi.cms.domain.vo.DictVo;
import com.ruoyi.cms.domain.vo.EchartsVo;
import com.ruoyi.cms.domain.vo.JobDemandTreadDemandVo;
import com.ruoyi.cms.domain.vo.JobDemandTreadEconomyCorrelationVo;
import com.ruoyi.cms.domain.vo.JobDemandTreadGDPCorrelationVo;
import com.ruoyi.cms.domain.vo.JobDemandTreadOverviewVo;
import com.ruoyi.cms.domain.vo.QueryResultVo;
import com.ruoyi.cms.domain.vo.SkillKeywordVo;
import java.util.List;
/**
* 岗位需求趋势变化分析
*
* @author 马宝龙
* @date 2026/6/26
*/
public interface AnalysisJobDemandTreadService {
/**
* 数据总览
*
* @param dto 查询参数
* @return 数据总览
*/
JobDemandTreadOverviewVo overview(QueryParamDto dto);
/**
* 宏观经济与岗位需求关联
*
* @param dto 查询参数
* @return 结果列表
*/
List<JobDemandTreadEconomyCorrelationVo> economyAndJobDemandCorrelation(QueryParamDto dto);
/**
* 热门岗位Top10排名
*
* @param dto 查询参数
* @return 结果列表
*/
List<QueryResultVo> hotJobRank(QueryParamDto dto);
/**
* GDP与岗位需求相关性分析
*
* @param dto 查询参数
* @return 结果列表
*/
List<JobDemandTreadGDPCorrelationVo> gdpAndJobDemandCorrelation(QueryParamDto dto);
/**
* 岗位类型占比变化趋势
*
* @param dto 查询参数
* @return 趋势数据
*/
EchartsVo jobTypePercentageTread(QueryParamDto dto);
/**
* 岗位需求总量
*
* @param dto 查询参数
* @return 趋势数据
*/
List<JobDemandTreadDemandVo> jobDemandCountTread(QueryParamDto dto);
/**
* 查询职业列表
*
* @return 职业列表
*/
List<DictVo> occupationList();
/**
* 技能关键词
*
* @param dto 查询参数
* @return 结果列表
*/
List<SkillKeywordVo> skillKeyword(QueryParamDto dto);
}

View File

@@ -0,0 +1,200 @@
package com.ruoyi.cms.service.impl;
import com.ruoyi.cms.domain.dto.QueryParamDto;
import com.ruoyi.cms.domain.vo.DictVo;
import com.ruoyi.cms.domain.vo.EchartsSeriesVo;
import com.ruoyi.cms.domain.vo.EchartsVo;
import com.ruoyi.cms.domain.vo.JobDemandTreadDemandVo;
import com.ruoyi.cms.domain.vo.JobDemandTreadEconomyCorrelationVo;
import com.ruoyi.cms.domain.vo.JobDemandTreadGDPCorrelationVo;
import com.ruoyi.cms.domain.vo.JobDemandTreadOverviewVo;
import com.ruoyi.cms.domain.vo.QueryResultVo;
import com.ruoyi.cms.domain.vo.SkillKeywordVo;
import com.ruoyi.cms.service.AnalysisJobDemandTreadService;
import com.ruoyi.cms.util.MathUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import reactor.util.function.Tuple2;
import reactor.util.function.Tuples;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
/**
* 岗位需求趋势变化分析
*
* @author 马宝龙
* @date 2026/6/26
*/
@Service
@Validated
@Slf4j
public class AnalysisJobDemandTreadServiceImpl implements AnalysisJobDemandTreadService {
@Override
public JobDemandTreadOverviewVo overview(QueryParamDto dto) {
return JobDemandTreadOverviewVo.builder()
.jobDemandCount(85000L)
.jobDemandCountMom(BigDecimal.valueOf(6.2))
.demandSupplyRate(BigDecimal.valueOf(1.35))
.demandSupplyRateMom(BigDecimal.valueOf(0.05))
.technicalJobPercentage(BigDecimal.valueOf(42.5))
.technicalJobPercentageMom(BigDecimal.valueOf(2.3))
.hardSkillDemandCount(32000L)
.hardSkillDemandCountMom(BigDecimal.valueOf(8.1))
.build();
}
@Override
public List<JobDemandTreadEconomyCorrelationVo> economyAndJobDemandCorrelation(QueryParamDto dto) {
List<JobDemandTreadEconomyCorrelationVo> list = new ArrayList<>();
for (int i = 0; i < 12; i++) {
list.add(JobDemandTreadEconomyCorrelationVo.builder()
.code(i + 1 + "")
.desc(i + 1 + "")
.gdpGrowthRate(BigDecimal.valueOf(Math.random() * 5 + 2).setScale(1, RoundingMode.HALF_UP))
.cpiYoyRate(BigDecimal.valueOf(Math.random() * 3 + 1).setScale(1, RoundingMode.HALF_UP))
.pmiIndex(BigDecimal.valueOf(Math.random() * 10 + 45).setScale(1, RoundingMode.HALF_UP))
.jobDemandCount((long) Math.floor(Math.random() * 20000) + 5000)
.build());
}
return list;
}
@Override
public List<QueryResultVo> hotJobRank(QueryParamDto dto) {
List<QueryResultVo> list = new ArrayList<>();
List<Tuple2<String, String>> jobList =
Collections.unmodifiableList(new ArrayList<>(Arrays.asList(
Tuples.of("1", "软件工程师"),
Tuples.of("2", "数据分析师"),
Tuples.of("3", "销售经理"),
Tuples.of("4", "机械工程师"),
Tuples.of("5", "电气工程师"),
Tuples.of("6", "财务会计"),
Tuples.of("7", "市场营销"),
Tuples.of("8", "人力资源"),
Tuples.of("9", "客服专员"),
Tuples.of("10", "物流管理")
)));
for (Tuple2<String, String> job : jobList) {
list.add(QueryResultVo.builder()
.code(job.getT1())
.desc(job.getT2())
.count((long) Math.floor(Math.random() * 100000) + 1)
.build());
}
return list;
}
@Override
public List<JobDemandTreadGDPCorrelationVo> gdpAndJobDemandCorrelation(QueryParamDto dto) {
List<JobDemandTreadGDPCorrelationVo> list = new ArrayList<>();
for (int i = 0; i < 12; i++) {
list.add(JobDemandTreadGDPCorrelationVo.builder()
.gdpIndex(BigDecimal.valueOf(Math.random() * 5 + 1).setScale(1, RoundingMode.HALF_UP))
.jobDemandCount((long) Math.floor(Math.random() * 20000) + 5000)
.build());
}
return list;
}
@Override
public EchartsVo jobTypePercentageTread(QueryParamDto dto) {
List<String> xAxis = IntStream.rangeClosed(1, 12)
.mapToObj(i -> i + "")
.collect(Collectors.toList());
List<Tuple2<String, String>> typeList =
Collections.unmodifiableList(new ArrayList<>(Arrays.asList(
Tuples.of("1", "技术类"),
Tuples.of("2", "管理类"),
Tuples.of("3", "操作类"),
Tuples.of("4", "其他")
)));
List<EchartsSeriesVo> series = new ArrayList<>();
for (Tuple2<String, String> type : typeList) {
List<Long> dataList = new ArrayList<>();
for (int i = 0; i < 12; i++) {
dataList.add((long) Math.floor(Math.random() * 40) + 10);
}
series.add(EchartsSeriesVo.builder().name(type.getT2()).data(dataList).build());
}
return EchartsVo.builder().xAxis(xAxis).series(series).build();
}
@Override
public List<JobDemandTreadDemandVo> jobDemandCountTread(QueryParamDto dto) {
List<JobDemandTreadDemandVo> list = new ArrayList<>();
for (int i = 0; i < 12; i++) {
long demand = (long) Math.floor(Math.random() * 20000) + 5000;
long supply = (long) Math.floor(Math.random() * 15000) + 3000;
BigDecimal rate = MathUtil.calculatePercentage(demand, supply);
list.add(JobDemandTreadDemandVo.builder()
.code(i + 1 + "")
.desc(i + 1 + "")
.jobDemandCount(demand)
.lobarSupplyCount(supply)
.demandSupplyRate(rate)
.demandSupplyRateMom(BigDecimal.valueOf(Math.random() * 0.3 - 0.15).setScale(2,
RoundingMode.HALF_UP))
.build());
}
return list;
}
@Override
public List<DictVo> occupationList() {
List<DictVo> list = new ArrayList<>();
List<Tuple2<String, String>> occupationList =
Collections.unmodifiableList(new ArrayList<>(Arrays.asList(
Tuples.of("1", "软件开发"),
Tuples.of("2", "数据分析"),
Tuples.of("3", "机械制造"),
Tuples.of("4", "电气工程"),
Tuples.of("5", "财务会计"),
Tuples.of("6", "市场营销"),
Tuples.of("7", "行政管理"),
Tuples.of("8", "物流配送")
)));
for (Tuple2<String, String> occupation : occupationList) {
list.add(DictVo.builder().code(occupation.getT1()).desc(occupation.getT2()).build());
}
return list;
}
@Override
public List<SkillKeywordVo> skillKeyword(QueryParamDto dto) {
List<SkillKeywordVo> list = new ArrayList<>();
List<Tuple2<String, String>> keywordList =
Collections.unmodifiableList(new ArrayList<>(Arrays.asList(
Tuples.of("Python", "硬技能"),
Tuples.of("Java", "硬技能"),
Tuples.of("数据分析", "硬技能"),
Tuples.of("项目管理", "软技能"),
Tuples.of("团队协作", "软技能"),
Tuples.of("机器学习", "硬技能"),
Tuples.of("沟通能力", "软技能"),
Tuples.of("SQL", "硬技能"),
Tuples.of("智能制造", "硬技能"),
Tuples.of("英语", "硬技能")
)));
for (Tuple2<String, String> keyword : keywordList) {
list.add(SkillKeywordVo.builder()
.keyword(keyword.getT1())
.type(keyword.getT2())
.count((long) Math.floor(Math.random() * 2000) + 1)
.build());
}
return list;
}
}