合并测试环境最新后端代码

This commit is contained in:
2026-07-25 22:20:38 +08:00
20 changed files with 683 additions and 28 deletions

View File

@@ -0,0 +1,68 @@
package com.ruoyi.cms.controller.app;
import com.ruoyi.cms.domain.msg.HrUserBehaviorRecord;
import com.ruoyi.cms.service.msg.HrUserBehaviorRecordService;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.SiteSecurityUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/app/behavior")
@Api(tags = "移动端:行为记录")
public class HrUserBehaviorRecordController extends BaseController {
@Autowired
private HrUserBehaviorRecordService hrUserBehaviorRecordService;
/**
* 查询行为记录列表
*/
@GetMapping("/list")
@ApiOperation("查询行为记录列表")
public TableDataInfo list(HrUserBehaviorRecord hrUserBehaviorRecord) {
if (!SiteSecurityUtils.isLogin()) {
throw new ServiceException("用户未登录");
}
Long userId = SiteSecurityUtils.getUserId();
boolean admin = SiteSecurityUtils.isAdmin(userId);
if (!admin) {
hrUserBehaviorRecord.setActorId(userId);
} else {
hrUserBehaviorRecord.setActorId(null);
}
startPage();
List<HrUserBehaviorRecord> list = hrUserBehaviorRecordService.selectBehaviorRecordList(hrUserBehaviorRecord);
return getDataTable(list);
}
/**
* 上报浏览行为/投递行为
*/
@ApiOperation("上报浏览行为/投递行为")
@PostMapping("/report")
public AjaxResult reportBehavior(@RequestBody HrUserBehaviorRecord record) {
HrUserBehaviorRecord exist = hrUserBehaviorRecordService.getExistViewRecord(
record.getActorType(),
record.getActorId(),
record.getTargetType(),
record.getTargetId()
);
if (exist == null) {
record.setViewNum(1);
hrUserBehaviorRecordService.save(record);
} else {
exist.setViewNum(exist.getViewNum() + 1);
exist.setViewDuration(exist.getViewDuration() + record.getViewDuration());
hrUserBehaviorRecordService.updateById(exist);
}
return success();
}
}

View File

@@ -0,0 +1,74 @@
package com.ruoyi.cms.controller.cms;
import com.ruoyi.cms.domain.msg.HrUserBehaviorRecord;
import com.ruoyi.cms.service.msg.HrUserBehaviorRecordService;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.SiteSecurityUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/cms/behavior")
@Api(tags = "后台:行为记录")
public class CmsHrUserBehaviorRecordController extends BaseController {
@Autowired
private HrUserBehaviorRecordService hrUserBehaviorRecordService;
/**
* 查询行为记录列表
*/
@GetMapping("/list")
@PreAuthorize("@ss.hasPermi('cms:behavior:list')")
@ApiOperation("查询行为记录列表")
public TableDataInfo list(HrUserBehaviorRecord hrUserBehaviorRecord) {
if (!SiteSecurityUtils.isLogin()) {
throw new ServiceException("用户未登录");
}
Long userId = SiteSecurityUtils.getUserId();
boolean admin = SiteSecurityUtils.isAdmin(userId);
if (!admin) {
hrUserBehaviorRecord.setActorId(userId);
} else {
hrUserBehaviorRecord.setActorId(null);
}
startPage();
List<HrUserBehaviorRecord> list = hrUserBehaviorRecordService.selectBehaviorRecordList(hrUserBehaviorRecord);
return getDataTable(list);
}
/**
* 上报浏览行为/投递行为
*/
@ApiOperation("上报浏览行为/投递行为")
//@PreAuthorize("@ss.hasPermi('cms:behavior:report')")
@Log(title = "浏览行为", businessType = BusinessType.INSERT)
@PostMapping("/report")
public AjaxResult reportBehavior(@RequestBody HrUserBehaviorRecord record) {
HrUserBehaviorRecord exist = hrUserBehaviorRecordService.getExistViewRecord(
record.getActorType(),
record.getActorId(),
record.getTargetType(),
record.getTargetId()
);
if (exist == null) {
record.setViewNum(1);
hrUserBehaviorRecordService.save(record);
} else {
exist.setViewNum(exist.getViewNum() + 1);
exist.setViewDuration(exist.getViewDuration() + record.getViewDuration());
hrUserBehaviorRecordService.updateById(exist);
}
return success();
}
}

View File

@@ -173,4 +173,7 @@ public class ESJobDocument
@ApiModelProperty("重点人群-1农民工、2团场职工、3失业人员、4零就业家庭、5零工人员、6退役军人")
private String keyPopulations;
@ApiModelProperty("岗位特征行政、后勤、管理、技术、销售等字典job_feature添加")
private String jobFeature;
}

View File

@@ -254,6 +254,9 @@ public class Job extends BaseEntity
@ApiModelProperty("状态 0上架1下架")
private String jobStatus;
@ApiModelProperty("岗位特征行政、后勤、管理、技术、销售等字典job_feature添加")
private String jobFeature;
@TableField(exist = false)
@ApiModelProperty("户外招聘会岗位审核状态")
private String fairReviewStatus;

View File

@@ -0,0 +1,59 @@
package com.ruoyi.cms.domain.msg;
import com.baomidou.mybatisplus.annotation.*;
import com.ruoyi.common.core.domain.BaseEntity;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
@ApiModel("求职招聘双方行为记录表")
@TableName("hr_user_behavior_record")
public class HrUserBehaviorRecord extends BaseEntity {
@TableField(exist = false)
private static final long serialVersionUID = 1L;
@TableId(type = IdType.AUTO)
private Long id;
/** 操作人类型1求职者 2招聘方 */
@ApiModelProperty("操作人类型1求职者 2招聘方")
private Integer actorType;
/** 操作人ID(求职者ID/企业用户ID) */
@ApiModelProperty("操作人ID(求职者ID/企业用户ID) ")
private Long actorId;
/** 浏览目标类型1简历 2岗位 */
@ApiModelProperty("浏览目标类型1简历 2岗位")
private Integer targetType;
/** 目标ID(简历ID/岗位ID) */
@ApiModelProperty("目标ID(简历ID/岗位ID)")
private Long targetId;
/** 行为类型1阅览 2投递简历 */
@ApiModelProperty("行为类型1阅览 2投递简历")
private Integer behaviorType;
/** 阅览时长(单位:秒) */
@ApiModelProperty("阅览时长(单位:秒)")
private Integer viewDuration;
/** 阅览次数,多次打开累加 */
@ApiModelProperty("阅览次数,多次打开累加")
private Integer viewNum;
/** 状态1正常 */
@ApiModelProperty("状态1正常")
private Integer behaviorStatus;
/**开始时间*/
@TableField(exist = false)
private String beginTime;
/**截至时间*/
@TableField(exist = false)
private String endTime;
}

View File

@@ -1,7 +1,7 @@
package com.ruoyi.cms.domain.query;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.ruoyi.cms.domain.Job;
import com.ruoyi.common.core.domain.entity.UserWorkExperiences;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@@ -63,4 +63,13 @@ public class ESJobSearch extends Job
//结束时间
private Date endDate;
/**岗位收藏集合*/
private List<String> collectNames;
/**岗位申请集合*/
private List<String> applyNames;
/**工作经历*/
private List<UserWorkExperiences> userWorkExperiences;
}

View File

@@ -42,4 +42,6 @@ public interface JobApplyMapper extends BaseMapper<JobApply>
int updateJobZphApply(JobApply jobApply);
JobApply selectByJobIdAndUserId(@Param("jobId") Long jobId, @Param("userId") Long userId);
List<String> queryApplyNames(@Param("userId") Long userId);
}

View File

@@ -5,6 +5,7 @@ import java.util.List;
import com.ruoyi.cms.domain.Job;
import com.ruoyi.cms.domain.JobCollection;
import org.apache.ibatis.annotations.Param;
/**
* 用户岗位收藏Mapper接口
@@ -24,4 +25,6 @@ public interface JobCollectionMapper extends BaseMapper<JobCollection>
List<Job> collectionJob(Long userId);
public List<Job> selectJobCollectionListJob(JobCollection jobCollection);
List<String> queryCollectNames(@Param("userId") Long userId);
}

View File

@@ -0,0 +1,11 @@
package com.ruoyi.cms.mapper.msg;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.ruoyi.cms.domain.msg.HrUserBehaviorRecord;
import java.util.List;
public interface HrUserBehaviorRecordMapper extends BaseMapper<HrUserBehaviorRecord> {
List<HrUserBehaviorRecord> selectBehaviorRecordList(HrUserBehaviorRecord hrUserBehaviorRecord);
}

View File

@@ -598,6 +598,14 @@ public class AppUserServiceImpl extends ServiceImpl<AppUserMapper,AppUser> imple
List<AppSkill> skillList=appSkillMapper.getList(parmsk);
appUser.setAppSkillsList(skillList);
//查询教育经历
List<AppUserEducation> educationsList=appUserEducationMapper.selectEducationListByUserId(appUser.getUserId());
appUser.setEducationsList(educationsList);
//查询培训经历
List<AppUserTrain> trainsList=appUserTrainMapper.selectTrainListByUserId(appUser.getUserId());
appUser.setTrainsList(trainsList);
//查询附件
File fileParm=new File();
fileParm.setBussinessid(appUser.getUserId());

View File

@@ -166,20 +166,17 @@ public class CompanyServiceImpl extends ServiceImpl<CompanyMapper, Company> impl
}
int i=companyMapper.updateById(company);
if(i>0){
companyContactMapper.update(null,Wrappers.<CompanyContact>lambdaUpdate()
.eq(CompanyContact::getCompanyId, company.getCompanyId())
.set(CompanyContact::getDelFlag, Constants.Del_FLAG_DELETE));
List<CompanyContact> contactList = company.getCompanyContactList();
if (!Objects.isNull(contactList)) {
for (CompanyContact x : contactList) {
if (x.getId() != null) {
companyContactMapper.updateById(x);
} else {
x.setCompanyId(company.getCompanyId());
companyContactMapper.insert(x);
List<CompanyContact> contactList = company.getCompanyContactList();
if (!Objects.isNull(contactList)) {
for (CompanyContact x : contactList) {
if (x.getId() != null) {
companyContactMapper.updateById(x);
} else {
x.setCompanyId(company.getCompanyId());
companyContactMapper.insert(x);
}
}
}
}
if (companyNatureChanged) {
List<Long> jobIds = jobMapper.selectList(Wrappers.<Job>lambdaQuery()
.eq(Job::getCompanyId, company.getCompanyId()))

View File

@@ -2,21 +2,20 @@ package com.ruoyi.cms.service.impl;
import com.alibaba.fastjson.JSON;
import com.ruoyi.cms.domain.vo.CompanyVo;
import com.ruoyi.cms.mapper.AppUserBlockCompanyMapper;
import com.ruoyi.cms.mapper.CompanyMapper;
import com.ruoyi.cms.mapper.*;
import com.ruoyi.cms.service.ICompanyService;
import com.ruoyi.cms.util.remommend.JobRecommendUtil;
import com.ruoyi.common.core.domain.entity.AppUser;
import com.ruoyi.cms.domain.ESJobDocument;
import com.ruoyi.cms.domain.Job;
import com.ruoyi.cms.domain.query.ESJobSearch;
import com.ruoyi.cms.mapper.es.EsJobDocumentMapper;
import com.ruoyi.cms.mapper.JobMapper;
import com.ruoyi.cms.mapper.JobTitleMapper;
import com.ruoyi.cms.service.IESJobSearchService;
import com.ruoyi.common.core.domain.entity.JobTitle;
import com.ruoyi.cms.util.ListUtil;
import com.ruoyi.cms.util.StringUtil;
import com.ruoyi.common.core.domain.entity.Company;
import com.ruoyi.common.core.domain.entity.UserWorkExperiences;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.core.text.Convert;
import com.ruoyi.common.utils.DateUtils;
@@ -62,6 +61,12 @@ public class ESJobSearchImpl implements IESJobSearchService
private RedisCache redisCache;
@Autowired
private AppUserBlockCompanyMapper appUserBlockCompanyMapper;
@Autowired
private JobApplyMapper jobApplyMapper;
@Autowired
private JobCollectionMapper jobCollectionMapper;
@Autowired
private UserWorkExperiencesMapper userWorkExperiencesMapper;
// 锁的key唯一标识ES索引初始化
private static final String ES_INIT_LOCK_KEY = "es:job_document:init:lock";
@@ -245,15 +250,12 @@ public class ESJobSearchImpl implements IESJobSearchService
//查询
if(SiteSecurityUtils.isLogin()){
AppUser appUser = appUserService.selectAppUserByUserId(SiteSecurityUtils.getUserId());
List<Long> jobs=appUserBlockCompanyMapper.selectBlockCompanyIdsByUserIdJobs(appUser.getUserId());
if (jobs != null) {
jobIds.addAll(jobs.stream().distinct().collect(Collectors.toList()));
}
if (!StringUtil.isEmptyOrNull(esJobSearch.getCode())) {
newSearch.setCode(esJobSearch.getCode());
}
//求职者
if (!isCompanyUser) {
setJobSeekerParams(appUser, esJobSearch, newSearch);
setJobSeekerParams(appUser, esJobSearch, newSearch,jobIds);
}
}
@@ -327,7 +329,7 @@ public class ESJobSearchImpl implements IESJobSearchService
* @param esJobSearch
* @param newSearch
*/
private void setJobSeekerParams(AppUser appUser, ESJobSearch esJobSearch, ESJobSearch newSearch) {
private void setJobSeekerParams(AppUser appUser, ESJobSearch esJobSearch, ESJobSearch newSearch,List<Long> jobIds) {
if(!ListUtil.isEmptyOrNull(appUser.getJobTitle())){
List<String> jobTitle = appUser.getJobTitle();
newSearch.setJobTitle(String.join(",", jobTitle));
@@ -348,9 +350,10 @@ public class ESJobSearchImpl implements IESJobSearchService
if(!StringUtil.isEmptyOrNull(esJobSearch.getArea())){
newSearch.setArea(esJobSearch.getArea());
}
if(!StringUtil.isEmptyOrNull(appUser.getWorkExperience())){
newSearch.setExperience(appUser.getWorkExperience());
}
//影响后面按照经验打分,先注释
// if(!StringUtil.isEmptyOrNull(appUser.getWorkExperience())){
// newSearch.setExperience(appUser.getWorkExperience());
// }
if(!StringUtil.isEmptyOrNull(esJobSearch.getExperience())){
newSearch.setExperience(esJobSearch.getExperience());
}
@@ -379,6 +382,22 @@ public class ESJobSearchImpl implements IESJobSearchService
if(!StringUtil.isEmptyOrNull(esJobSearch.getCompanyNature())){
newSearch.setCompanyNature(esJobSearch.getCompanyNature());
}
//屏蔽企业集合
List<Long> jobs=appUserBlockCompanyMapper.selectBlockCompanyIdsByUserIdJobs(appUser.getUserId());
if (jobs != null) {
jobIds.addAll(jobs.stream().distinct().collect(Collectors.toList()));
}
//查询投递集合
List<String> applyNames=jobApplyMapper.queryApplyNames(appUser.getUserId());
newSearch.setApplyNames(applyNames);
//查询收藏集合
List<String> collectNames=jobCollectionMapper.queryCollectNames(appUser.getUserId());
newSearch.setCollectNames(collectNames);
//工作经历集合
UserWorkExperiences expQuery = new UserWorkExperiences();
expQuery.setUserId(appUser.getUserId());
List<UserWorkExperiences> userWorkExperiences=userWorkExperiencesMapper.getWorkExperiencesList(expQuery);
newSearch.setUserWorkExperiences(userWorkExperiences);
}
/**
@@ -644,6 +663,13 @@ public class ESJobSearchImpl implements IESJobSearchService
if(!StringUtil.isEmptyOrNull(esJobSearch.getCompanyName())){
wrapper.and(x->x.like(ESJobDocument::getCompanyName,esJobSearch.getCompanyName()));
}
// 1.简历工作经历(最高权重)
JobRecommendUtil.appendWorkExpMatch(wrapper, esJobSearch.getUserWorkExperiences());
//投递记录
JobRecommendUtil.appendJobTitleMatch(wrapper, esJobSearch.getApplyNames(), JobRecommendUtil.APPLY_TITLE_BOOST);
//收藏记录
JobRecommendUtil.appendJobTitleMatch(wrapper, esJobSearch.getCollectNames(), JobRecommendUtil.COLLECT_TITLE_BOOST);
//按时间段来查询数据
Date startDate = esJobSearch.getStartDate();
Date endDate = esJobSearch.getEndDate();
@@ -1030,6 +1056,17 @@ public class ESJobSearchImpl implements IESJobSearchService
if(!StringUtil.isEmptyOrNull(appUser.getSalaryMin())){
newSearch.setMinSalary(Long.valueOf(appUser.getSalaryMin()));
}
//查询投递集合
List<String> applyNames=jobApplyMapper.queryApplyNames(appUser.getUserId());
newSearch.setApplyNames(applyNames);
//查询收藏集合
List<String> collectNames=jobCollectionMapper.queryCollectNames(appUser.getUserId());
newSearch.setCollectNames(collectNames);
//工作经历集合
UserWorkExperiences expQuery = new UserWorkExperiences();
expQuery.setUserId(appUser.getUserId());
List<UserWorkExperiences> userWorkExperiences=userWorkExperiencesMapper.getWorkExperiencesList(expQuery);
newSearch.setUserWorkExperiences(userWorkExperiences);
}
// 请求参数始终优先于用户资料偏好
@@ -1263,4 +1300,19 @@ public class ESJobSearchImpl implements IESJobSearchService
return -1;
}
}
/**
* 岗位名称推荐
* @param wrapper
* @param nameList
* @param boost
*/
/*private void appendJobTitleMatch(LambdaEsQueryWrapper<ESJobDocument> wrapper, List<String> nameList, Float boost) {
if (CollUtil.isEmpty(nameList)) {
return;
}
for (String title : nameList) {
wrapper.should(w -> w.match(ESJobDocument::getJobTitle, title, boost));
}
}*/
}

View File

@@ -0,0 +1,39 @@
package com.ruoyi.cms.service.msg;
import com.baomidou.mybatisplus.extension.service.IService;
import com.ruoyi.cms.domain.msg.HrUserBehaviorRecord;
import java.util.List;
public interface HrUserBehaviorRecordService extends IService<HrUserBehaviorRecord> {
/**
* 查询行为记录列表
*/
List<HrUserBehaviorRecord> selectBehaviorRecordList(HrUserBehaviorRecord queryVo);
/**
* 新增行为记录
*/
int insertBehaviorRecord(HrUserBehaviorRecord record);
/**
* 修改行为记录
*/
int updateBehaviorRecord(HrUserBehaviorRecord record);
/**
* 批量删除
*/
int deleteBehaviorRecordByIds(Long[] ids);
/**
* 根据ID查询
*/
HrUserBehaviorRecord selectBehaviorRecordById(Long id);
/**
* 【业务埋点】查找同一主体同一目标当天浏览记录(用于累加次数、时长)
*/
HrUserBehaviorRecord getExistViewRecord(Integer actorType, Long actorId, Integer targetType, Long targetId);
}

View File

@@ -0,0 +1,60 @@
package com.ruoyi.cms.service.msg.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.cms.domain.msg.HrUserBehaviorRecord;
import com.ruoyi.cms.mapper.msg.HrUserBehaviorRecordMapper;
import com.ruoyi.cms.service.msg.HrUserBehaviorRecordService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.time.LocalDate;
import java.util.Arrays;
import java.util.List;
@Service
public class HrUserBehaviorRecordServiceImpl extends ServiceImpl<HrUserBehaviorRecordMapper, HrUserBehaviorRecord>
implements HrUserBehaviorRecordService {
@Autowired
private HrUserBehaviorRecordMapper hrUserBehaviorRecordMapper;
@Override
public List<HrUserBehaviorRecord> selectBehaviorRecordList(HrUserBehaviorRecord hrUserBehaviorRecord) {
return hrUserBehaviorRecordMapper.selectBehaviorRecordList(hrUserBehaviorRecord);
}
@Override
public int insertBehaviorRecord(HrUserBehaviorRecord record) {
return hrUserBehaviorRecordMapper.insert(record);
}
@Override
public int updateBehaviorRecord(HrUserBehaviorRecord record) {
return hrUserBehaviorRecordMapper.updateById(record);
}
@Override
public int deleteBehaviorRecordByIds(Long[] ids) {
return hrUserBehaviorRecordMapper.deleteBatchIds(Arrays.asList(ids));
}
@Override
public HrUserBehaviorRecord selectBehaviorRecordById(Long id) {
return hrUserBehaviorRecordMapper.selectById(id);
}
@Override
public HrUserBehaviorRecord getExistViewRecord(Integer actorType, Long actorId, Integer targetType, Long targetId) {
LambdaQueryWrapper<HrUserBehaviorRecord> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(HrUserBehaviorRecord::getActorType, actorType);
wrapper.eq(HrUserBehaviorRecord::getActorId, actorId);
wrapper.eq(HrUserBehaviorRecord::getTargetType, targetType);
wrapper.eq(HrUserBehaviorRecord::getTargetId, targetId);
LocalDate today = LocalDate.now();
wrapper.ge(HrUserBehaviorRecord::getCreateTime, today.atStartOfDay());
wrapper.le(HrUserBehaviorRecord::getCreateTime, today.atTime(23,59,59));
wrapper.last("limit 1");
return baseMapper.selectOne(wrapper);
}
}

View File

@@ -0,0 +1,177 @@
package com.ruoyi.cms.util.remommend;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.ruoyi.cms.domain.ESJobDocument;
import com.ruoyi.common.core.domain.entity.UserWorkExperiences;
import org.dromara.easyes.core.conditions.select.LambdaEsQueryWrapper;
import java.time.LocalDate;
import java.time.Period;
import java.util.*;
/**
* 岗位推荐查询条件工具类
* 权重规则:
* 简历岗位名称4/6/7 > 投递名称(3) > 收藏名称(2)
* 经验区间字典:
* 0=经验不限,1=实习生,2=应届毕业生,3=1年以下,4=1-3年,5=3-5年,6=5-10年,7=10年以上
*/
public class JobRecommendUtil {
// =====================权重常量,集中调参=====================
/** 工作经历岗位名称任职不足1年 */
public static final Float POS_BOOST_SHORT = 4F;
/** 工作经历岗位名称1~3年 */
public static final Float POS_BOOST_MID = 6F;
/** 工作经历岗位名称:>=3年 */
public static final Float POS_BOOST_LONG = 7F;
/** 投递岗位名称权重 */
public static final Float APPLY_TITLE_BOOST = 3F;
/** 收藏岗位名称权重 */
public static final Float COLLECT_TITLE_BOOST = 2F;
/** 经验区间匹配权重 */
public static final Float EXP_MATCH_SELF = 3F;
public static final Float EXP_MATCH_LOW1 = 2F;
public static final Float EXP_MATCH_LOWER = 1F;
// =====================基础计算方法=====================
/**
* 计算单条工作经历时长(月)
* @param startDateStr 开始年月 yyyy-MM
* @param endDateStr 结束年月 yyyy-MMnull代表至今在职
*/
public static int calcWorkMonth(String startDateStr, String endDateStr) {
if (StrUtil.isBlank(startDateStr)) {
return 0;
}
LocalDate start = LocalDate.parse(startDateStr + "-01");
LocalDate end;
if (StrUtil.isBlank(endDateStr)) {
end = LocalDate.now();
} else {
end = LocalDate.parse(endDateStr + "-01");
}
Period period = Period.between(start, end);
return period.getYears() * 12 + period.getMonths();
}
/**
* 计算全部工作经历总月数(简单累加,不处理时间重叠)
*/
public static int calcTotalWorkMonth(List<UserWorkExperiences> expList) {
if (CollUtil.isEmpty(expList)) {
return 0;
}
return expList.stream()
.mapToInt(exp -> calcWorkMonth(exp.getStartDate(), exp.getEndDate()))
.sum();
}
/**
* 总工作月数 → 转换经验编码
*/
public static Integer convertMonthToExpCode(int totalMonth) {
if (totalMonth <= 0) {
// 无工作经历:应届生
return 2;
}
double year = totalMonth / 12.0;
if (year < 1) {
return 3;
} else if (year <= 3) {
return 4;
} else if (year <= 5) {
return 5;
} else if (year <= 10) {
return 6;
} else {
return 7;
}
}
/**
* 追加简历工作经历匹配条件
* 1.岗位名称匹配
* 2.经验等级匹配
*/
public static <T> void appendWorkExpMatch(LambdaEsQueryWrapper<T> wrapper, List<UserWorkExperiences> expList) {
if (CollUtil.isEmpty(expList)) {
return;
}
Map<String, Float> posBoostMap = new HashMap<>();
for (UserWorkExperiences exp : expList) {
String position = exp.getPosition();
if (StrUtil.isBlank(position)) {
continue;
}
int month = calcWorkMonth(exp.getStartDate(), exp.getEndDate());
Float boost;
if (month >= 36) {
boost = POS_BOOST_LONG;
} else if (month >= 12) {
boost = POS_BOOST_MID;
} else {
boost = POS_BOOST_SHORT;
}
posBoostMap.compute(position, (k, old) -> old == null ? boost : Math.max(old, boost));
}
// 名称拼接,带上对应权重
for (Map.Entry<String, Float> entry : posBoostMap.entrySet()) {
String title = entry.getKey();
Float boost = entry.getValue();
wrapper.should(w -> w.match("jobTitle", title, boost));
}
// 经验区间梯度加权
int totalMonth = calcTotalWorkMonth(expList);
Integer userExpCode = convertMonthToExpCode(totalMonth);
appendExpCodeMatch(wrapper, userExpCode);
}
/**
* 根据用户经验编码追加经验等级should条件
*/
private static <T> void appendExpCodeMatch(LambdaEsQueryWrapper<T> wrapper, Integer userExpCode) {
// 应届生 / 实习生
if (userExpCode <= 2) {
wrapper.should(w -> w.match("experience_int", 0, EXP_MATCH_SELF));
wrapper.should(w -> w.match("experience_int", 1, EXP_MATCH_SELF));
wrapper.should(w -> w.match("experience_int", 2, EXP_MATCH_SELF));
return;
}
int selfCode = userExpCode;
int lower1 = selfCode - 1;
List<Integer> lowerAll = new ArrayList<>();
for (int i = 0; i < lower1; i++) {
lowerAll.add(i);
}
// 完全匹配自身经验区间,最高权重
wrapper.should(w -> w.match("experience_int", selfCode, EXP_MATCH_SELF));
// 低一档经验,次权重
wrapper.should(w -> w.match("experience_int", lower1, EXP_MATCH_LOW1));
// 低两档及经验不限,最低权重
for (Integer code : lowerAll) {
wrapper.should(w -> w.match("experience_int", code, EXP_MATCH_LOWER));
}
}
/**
* 批量追加岗位名称match投递/收藏通用)
* @param nameList 岗位名称集合
* @param boost 权重
*/
public static void appendJobTitleMatch(LambdaEsQueryWrapper<ESJobDocument> wrapper, List<String> nameList, Float boost) {
if (CollUtil.isEmpty(nameList)) {
return;
}
for (String title : nameList) {
wrapper.should(w -> w.match(ESJobDocument::getJobTitle, title, boost));
}
}
}

View File

@@ -200,4 +200,10 @@
<select id="selectByJobIdAndUserId" resultMap="JobApplyResult">
select * from job_apply where del_flag='0' and job_id=#{jobId} and user_id=#{userId}
</select>
<select id="queryApplyNames" resultType="java.lang.String">
select distinct j.job_title from job_apply ja inner join job j on ja.job_id=j.job_id
where ja.del_flag='0' and j.del_flag='0' and ja.user_id=#{userId}
and ja.create_time >= now() - interval '6' month
</select>
</mapper>

View File

@@ -44,4 +44,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="userId != null "> and a.user_id = #{userId}</if>
</where>
</select>
<select id="queryCollectNames" resultType="java.lang.String">
select distinct j.job_title
from job_collection jc inner join job j on jc.job_id = j.job_id
where jc.del_flag = '0' and j.del_flag = '0' and jc.user_id = #{userId}
and jc.create_time >= now() - interval '6' month
</select>
</mapper>

View File

@@ -45,6 +45,7 @@
<result property="reviewStatus" column="review_status" />
<result property="isKeyPopulations" column="is_key_populations" />
<result property="keyPopulations" column="key_populations" />
<result property="jobFeature" column="job_feature" />
</resultMap>
@@ -94,6 +95,7 @@
<result property="jobStatus" column="job_status" />
<result property="isKeyPopulations" column="is_key_populations" />
<result property="keyPopulations" column="key_populations" />
<result property="jobFeature" column="job_feature" />
<association property="companyVo" resultMap="CompanyResult"/>
<association property="jobContactList" resultMap="JomContactResult"/>
@@ -155,7 +157,7 @@
job_location_area_code, posting_date, vacancies, latitude, longitude, "view", company_id,
is_hot, is_urgent, apply_num, description, is_publish, data_source, job_url, remark, del_flag,
create_by, create_time, row_id, job_category,job_type,job_address,job_status,is_key_populations,
key_populations
key_populations,job_feature
) VALUES
<foreach collection="list" item="job" separator=",">
(
@@ -164,7 +166,8 @@
#{job.vacancies}, #{job.latitude}, #{job.longitude}, #{job.view}, #{job.companyId},
#{job.isHot}, #{job.isUrgent}, #{job.applyNum}, #{job.description}, #{job.isPublish}, #{job.dataSource},
#{job.jobUrl}, #{job.remark}, #{job.delFlag}, #{job.createBy}, #{job.createTime},
#{job.rowId}, #{job.jobCategory},#{job.jobType},#{job.jobAddress},#{job.jobStatus},#{job.isKeyPopulations},#{job.keyPopulations}
#{job.rowId}, #{job.jobCategory},#{job.jobType},#{job.jobAddress},#{job.jobStatus},#{job.isKeyPopulations},
#{job.keyPopulations},#{job.jobFeature}
)
</foreach>
</insert>

View File

@@ -0,0 +1,63 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.cms.mapper.msg.HrUserBehaviorRecordMapper">
<resultMap type="com.ruoyi.cms.domain.msg.HrUserBehaviorRecord" id="HrUserBehaviorRecordResult">
<id column="id" property="id"/>
<result column="actor_type" property="actorType"/>
<result column="actor_id" property="actorId"/>
<result column="target_type" property="targetType"/>
<result column="target_id" property="targetId"/>
<result column="behavior_type" property="behaviorType"/>
<result column="view_duration" property="viewDuration"/>
<result column="view_times" property="viewTimes"/>
<result column="behavior_status" property="behaviorStatus"/>
<result column="del_flag" property="delFlag"/>
<result column="create_by" property="createBy"/>
<result column="create_time" property="createTime"/>
<result column="update_by" property="updateBy"/>
<result column="update_time" property="updateTime"/>
<result column="remark" property="remark"/>
</resultMap>
<sql id="selectHrUserBehaviorRecordVo">
SELECT id, actor_type, actor_id, target_type, target_id, behavior_type,
view_duration, view_times, behavior_status, del_flag,
create_by, create_time, update_by, update_time, remark
FROM hr_user_behavior_record
</sql>
<!-- 查询列表 -->
<select id="selectBehaviorRecordList" resultMap="HrUserBehaviorRecordResult">
<include refid="selectHrUserBehaviorRecordVo"/>
<where> del_flag = '0'
<if test="actorType != null">
AND actor_type = #{actorType}
</if>
<if test="actorId != null">
AND actor_id = #{actorId}
</if>
<if test="targetType != null">
AND target_type = #{targetType}
</if>
<if test="targetId != null">
AND target_id = #{targetId}
</if>
<if test="behaviorType != null">
AND behavior_type = #{behaviorType}
</if>
<if test="behaviorStatus != null">
AND behavior_status = #{behaviorStatus}
</if>
<if test="beginTime != null">
AND create_time &gt;= #{beginTime}
</if>
<if test="endTime != null">
AND create_time &lt;= #{endTime}
</if>
</where>
ORDER BY create_time DESC
</select>
</mapper>

View File

@@ -150,4 +150,15 @@ public class SiteSecurityUtils
throw new ServiceException("获取用户ID异常", HttpStatus.UNAUTHORIZED);
}
}
/**
* 是否为管理员
*
* @param userId 用户ID
* @return 结果
*/
public static boolean isAdmin(Long userId)
{
return userId != null && 1L == userId;
}
}