Merge remote-tracking branch 'origin/main'
This commit is contained in:
@@ -99,7 +99,7 @@ public class AppOutdoorFairController extends BaseController
|
||||
@BussinessLog(title = "户外招聘会列表")
|
||||
@ApiOperation("分页查询户外招聘会列表")
|
||||
@GetMapping("/page")
|
||||
public PublicJobFairResponse page(PublicJobFairQuery query)
|
||||
public PublicJobFairResponse page(PublicJobFairQuery query, HttpServletRequest request)
|
||||
{
|
||||
if (query == null) {
|
||||
query = new PublicJobFairQuery();
|
||||
@@ -111,14 +111,14 @@ public class AppOutdoorFairController extends BaseController
|
||||
PublicJobFairResponse response = new PublicJobFairResponse();
|
||||
response.setCode(200);
|
||||
response.setMsg("查询成功");
|
||||
response.setData(buildPageData(page, pageNum, pageSize));
|
||||
response.setData(buildPageData(page, pageNum, pageSize, request));
|
||||
return response;
|
||||
}
|
||||
|
||||
@BussinessLog(title = "查看当季度户外招聘会信息")
|
||||
@ApiOperation("查看当季度户外招聘会信息")
|
||||
@GetMapping("/currentQuarter")
|
||||
public AjaxResult currentQuarterFairs()
|
||||
public AjaxResult currentQuarterFairs(HttpServletRequest request)
|
||||
{
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
int currentMonth = calendar.get(Calendar.MONTH);
|
||||
@@ -131,13 +131,13 @@ public class AppOutdoorFairController extends BaseController
|
||||
calendar.add(Calendar.MONTH, 3);
|
||||
Date endTime = calendar.getTime();
|
||||
|
||||
return success(listOutdoorFairsByRange(startTime, endTime));
|
||||
return success(listOutdoorFairsByRange(startTime, endTime, request));
|
||||
}
|
||||
|
||||
@BussinessLog(title = "查看当月户外招聘会信息")
|
||||
@ApiOperation("查看当月户外招聘会信息")
|
||||
@GetMapping("/currentMonth")
|
||||
public AjaxResult currentMonthFairs()
|
||||
public AjaxResult currentMonthFairs(HttpServletRequest request)
|
||||
{
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
calendar.set(Calendar.DAY_OF_MONTH, 1);
|
||||
@@ -147,7 +147,7 @@ public class AppOutdoorFairController extends BaseController
|
||||
calendar.add(Calendar.MONTH, 1);
|
||||
Date endTime = calendar.getTime();
|
||||
|
||||
return success(listOutdoorFairsByRange(startTime, endTime));
|
||||
return success(listOutdoorFairsByRange(startTime, endTime, request));
|
||||
}
|
||||
|
||||
@BussinessLog(title = "查询有户外招聘会的日期列表")
|
||||
@@ -206,7 +206,7 @@ public class AppOutdoorFairController extends BaseController
|
||||
return AjaxResult.error("招聘会不存在");
|
||||
}
|
||||
Map<String, Object> data = new HashMap<>();
|
||||
Map<String, Object> publicFair = buildPublicFairDetail(fair);
|
||||
Map<String, Object> publicFair = buildPublicFairDetail(fair, request);
|
||||
publicFair.put("checkedIn", hasCheckedIn(fairId));
|
||||
data.put("fair", publicFair);
|
||||
data.put("companies", buildPublicParticipatingCompanies(fairId));
|
||||
@@ -433,6 +433,7 @@ public class AppOutdoorFairController extends BaseController
|
||||
if (fair == null) {
|
||||
throw new ServiceException("招聘会不存在");
|
||||
}
|
||||
fair.setPhotoUrl(RequestUrlUtils.normalizePublicUrl(request, fair.getPhotoUrl()));
|
||||
Company company = companyMapper.selectById(companyId);
|
||||
if (company == null) {
|
||||
throw new ServiceException("企业不存在");
|
||||
@@ -497,11 +498,12 @@ public class AppOutdoorFairController extends BaseController
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
private PublicJobFairResponse.PageData buildPageData(Page<OutdoorFair> page, int pageNum, int pageSize)
|
||||
private PublicJobFairResponse.PageData buildPageData(Page<OutdoorFair> page, int pageNum, int pageSize,
|
||||
HttpServletRequest request)
|
||||
{
|
||||
PublicJobFairResponse.PageData data = new PublicJobFairResponse.PageData();
|
||||
List<PublicJobFair> list = page.getRecords().stream()
|
||||
.map(this::buildPublicJobFair)
|
||||
.map(fair -> buildPublicJobFair(fair, request))
|
||||
.collect(Collectors.toList());
|
||||
int pages = (int) page.getPages();
|
||||
data.setTotal(page.getTotal());
|
||||
@@ -534,18 +536,19 @@ public class AppOutdoorFairController extends BaseController
|
||||
return pageNums;
|
||||
}
|
||||
|
||||
private List<PublicJobFair> listOutdoorFairsByRange(Date startTime, Date endTime)
|
||||
private List<PublicJobFair> listOutdoorFairsByRange(Date startTime, Date endTime,
|
||||
HttpServletRequest request)
|
||||
{
|
||||
return outdoorFairService.list(new LambdaQueryWrapper<OutdoorFair>()
|
||||
.ge(OutdoorFair::getHoldTime, startTime)
|
||||
.lt(OutdoorFair::getHoldTime, endTime)
|
||||
.orderByAsc(OutdoorFair::getHoldTime))
|
||||
.stream()
|
||||
.map(this::buildPublicJobFair)
|
||||
.map(fair -> buildPublicJobFair(fair, request))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private PublicJobFair buildPublicJobFair(OutdoorFair fair)
|
||||
private PublicJobFair buildPublicJobFair(OutdoorFair fair, HttpServletRequest request)
|
||||
{
|
||||
PublicJobFair jobFair = new PublicJobFair();
|
||||
jobFair.setJobFairId(String.valueOf(fair.getId()));
|
||||
@@ -558,7 +561,7 @@ public class AppOutdoorFairController extends BaseController
|
||||
jobFair.setJobFairOrganizeUnit(fair.getHostUnit());
|
||||
jobFair.setJobFairIntroduction(fair.getFairIntroduction());
|
||||
jobFair.setJobFairProcess(fair.getFairProcess());
|
||||
jobFair.setJobFairImage(fair.getPhotoUrl());
|
||||
jobFair.setJobFairImage(RequestUrlUtils.normalizePublicUrl(request, fair.getPhotoUrl()));
|
||||
jobFair.setJobFairSignUpStartTime(fair.getApplyStartTime());
|
||||
jobFair.setJobFairSignUpEndTime(fair.getApplyEndTime());
|
||||
jobFair.setJobFairVenueId(fair.getVenueId() == null ? null : String.valueOf(fair.getVenueId()));
|
||||
@@ -570,7 +573,7 @@ public class AppOutdoorFairController extends BaseController
|
||||
* 公共(求职者)详情只保留公开招聘会资料。
|
||||
* 企业需携带资料与到场须知不能随实体直接序列化到公共接口。
|
||||
*/
|
||||
private Map<String, Object> buildPublicFairDetail(OutdoorFair fair)
|
||||
private Map<String, Object> buildPublicFairDetail(OutdoorFair fair, HttpServletRequest request)
|
||||
{
|
||||
Map<String, Object> publicFair = new HashMap<>();
|
||||
publicFair.put("id", fair.getId());
|
||||
@@ -587,7 +590,7 @@ public class AppOutdoorFairController extends BaseController
|
||||
publicFair.put("applyStartTime", fair.getApplyStartTime());
|
||||
publicFair.put("applyEndTime", fair.getApplyEndTime());
|
||||
publicFair.put("onlineApply", fair.getOnlineApply());
|
||||
publicFair.put("photoUrl", fair.getPhotoUrl());
|
||||
publicFair.put("photoUrl", RequestUrlUtils.normalizePublicUrl(request, fair.getPhotoUrl()));
|
||||
publicFair.put("fairIntroduction", fair.getFairIntroduction());
|
||||
publicFair.put("fairProcess", fair.getFairProcess());
|
||||
Long boothMapCount = outdoorFairBoothMapper.selectCount(new LambdaQueryWrapper<OutdoorFairBooth>()
|
||||
|
||||
@@ -59,13 +59,8 @@ public class HrUserBehaviorRecordController extends BaseController {
|
||||
record.setViewNum(1);
|
||||
hrUserBehaviorRecordService.save(record);
|
||||
} else {
|
||||
if (record.getViewDuration() > 0) {
|
||||
// 页面离开上报:累加时长
|
||||
exist.setViewDuration(exist.getViewDuration() + record.getViewDuration());
|
||||
} else {
|
||||
// 页面进入上报:次数+1
|
||||
exist.setViewNum(exist.getViewNum() + 1);
|
||||
}
|
||||
exist.setViewNum(exist.getViewNum() + 1);
|
||||
exist.setViewDuration(exist.getViewDuration() + record.getViewDuration());
|
||||
hrUserBehaviorRecordService.updateById(exist);
|
||||
}
|
||||
return success();
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -149,6 +149,7 @@ public class OutdoorFairController extends BaseController
|
||||
List<OutdoorFair> list = outdoorFairService.selectOutdoorFairList(
|
||||
outdoorFair, startTime, endTime, applyStartTime, applyEndTime);
|
||||
fillReservedBoothCount(list);
|
||||
normalizePhotoUrls(list, request);
|
||||
fillCompanyApplyState(list, request, company);
|
||||
return getDataTable(list);
|
||||
}
|
||||
@@ -159,12 +160,19 @@ public class OutdoorFairController extends BaseController
|
||||
@ApiOperation("获取户外招聘会详细信息")
|
||||
@PreAuthorize("@ss.hasPermi('cms:outdoorFair:query')")
|
||||
@GetMapping(value = "/{id}")
|
||||
public AjaxResult getInfo(@PathVariable("id") Long id)
|
||||
public AjaxResult getInfo(@PathVariable("id") Long id, HttpServletRequest request)
|
||||
{
|
||||
if (RoleUtils.isCompanyAdmin()) {
|
||||
return AjaxResult.error("企业用户无权查看招聘会详情");
|
||||
}
|
||||
return success(outdoorFairService.getById(id));
|
||||
OutdoorFair fair = outdoorFairService.getById(id);
|
||||
if (fair != null) {
|
||||
fair.setPhotoUrl(RequestUrlUtils.normalizePublicUrl(request, fair.getPhotoUrl()));
|
||||
Long boothMapCount = outdoorFairBoothMapper.selectCount(new LambdaQueryWrapper<OutdoorFairBooth>()
|
||||
.eq(OutdoorFairBooth::getFairId, id));
|
||||
fair.setBoothMapCount(boothMapCount == null ? 0 : boothMapCount.intValue());
|
||||
}
|
||||
return success(fair);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -466,6 +474,10 @@ public class OutdoorFairController extends BaseController
|
||||
if (RoleUtils.isCompanyAdmin()) {
|
||||
return AjaxResult.error("企业用户无权新增户外招聘会");
|
||||
}
|
||||
String photoValidationError = validatePhotoUrl(outdoorFair);
|
||||
if (photoValidationError != null) {
|
||||
return AjaxResult.error(photoValidationError);
|
||||
}
|
||||
String timeValidationError = validateRegistrationDeadline(outdoorFair);
|
||||
if (timeValidationError != null) {
|
||||
return AjaxResult.error(timeValidationError);
|
||||
@@ -491,6 +503,10 @@ public class OutdoorFairController extends BaseController
|
||||
if (RoleUtils.isCompanyAdmin()) {
|
||||
return AjaxResult.error("企业用户无权编辑户外招聘会");
|
||||
}
|
||||
String photoValidationError = validatePhotoUrl(outdoorFair);
|
||||
if (photoValidationError != null) {
|
||||
return AjaxResult.error(photoValidationError);
|
||||
}
|
||||
String timeValidationError = validateRegistrationDeadline(outdoorFair);
|
||||
if (timeValidationError != null) {
|
||||
return AjaxResult.error(timeValidationError);
|
||||
@@ -1381,11 +1397,38 @@ public class OutdoorFairController extends BaseController
|
||||
countMap.put(((Number) fairId).longValue(), ((Number) count).intValue());
|
||||
}
|
||||
}
|
||||
Map<Long, Integer> boothMapCountMap = new HashMap<>();
|
||||
for (Map<String, Object> row : outdoorFairBoothMapper.countBoothsByFairIds(fairIds)) {
|
||||
Object fairId = row.get("fairId");
|
||||
Object count = row.get("boothMapCount");
|
||||
if (fairId instanceof Number && count instanceof Number) {
|
||||
boothMapCountMap.put(((Number) fairId).longValue(), ((Number) count).intValue());
|
||||
}
|
||||
}
|
||||
for (OutdoorFair fair : fairs) {
|
||||
fair.setReservedBoothCount(countMap.getOrDefault(fair.getId(), 0));
|
||||
fair.setBoothMapCount(boothMapCountMap.getOrDefault(fair.getId(), 0));
|
||||
}
|
||||
}
|
||||
|
||||
private void normalizePhotoUrls(List<OutdoorFair> fairs, HttpServletRequest request)
|
||||
{
|
||||
if (fairs == null) {
|
||||
return;
|
||||
}
|
||||
for (OutdoorFair fair : fairs) {
|
||||
fair.setPhotoUrl(RequestUrlUtils.normalizePublicUrl(request, fair.getPhotoUrl()));
|
||||
}
|
||||
}
|
||||
|
||||
private String validatePhotoUrl(OutdoorFair outdoorFair)
|
||||
{
|
||||
if (outdoorFair != null && RequestUrlUtils.isLoopbackUrl(outdoorFair.getPhotoUrl())) {
|
||||
return "招聘会照片地址不能使用本机回环地址,请重新上传照片";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean hasFairBoothSnapshot(Long fairId)
|
||||
{
|
||||
if (fairId == null) {
|
||||
|
||||
@@ -173,4 +173,7 @@ public class ESJobDocument
|
||||
|
||||
@ApiModelProperty("重点人群-1农民工、2团场职工、3失业人员、4零就业家庭、5零工人员、6退役军人")
|
||||
private String keyPopulations;
|
||||
|
||||
@ApiModelProperty("岗位特征:(行政、后勤、管理、技术、销售等字典job_feature添加)")
|
||||
private String jobFeature;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -27,6 +27,18 @@ public class PublicJobFairDetail implements Serializable {
|
||||
@ApiModelProperty("招聘会地址")
|
||||
private String jobFairAddress;
|
||||
|
||||
@ApiModelProperty("主办单位")
|
||||
private String jobFairHostUnit;
|
||||
|
||||
@ApiModelProperty("协办单位")
|
||||
private String jobFairHelpUnit;
|
||||
|
||||
@ApiModelProperty("承办单位")
|
||||
private String jobFairOrganizeUnit;
|
||||
|
||||
@ApiModelProperty("联系电话")
|
||||
private String jobFairPhone;
|
||||
|
||||
@ApiModelProperty("招聘会简介")
|
||||
private String jobFairIntroduction;
|
||||
|
||||
@@ -38,6 +50,14 @@ public class PublicJobFairDetail implements Serializable {
|
||||
@ApiModelProperty("招聘会结束时间")
|
||||
private Date jobFairEndTime;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@ApiModelProperty("报名开始时间")
|
||||
private Date jobFairSignUpStartTime;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@ApiModelProperty("报名结束时间")
|
||||
private Date jobFairSignUpEndTime;
|
||||
|
||||
@ApiModelProperty("招聘会类型 1-线上 2-线下")
|
||||
private Integer jobFairType;
|
||||
|
||||
@@ -50,6 +70,12 @@ public class PublicJobFairDetail implements Serializable {
|
||||
@ApiModelProperty("经度")
|
||||
private BigDecimal longitude;
|
||||
|
||||
@ApiModelProperty("是否跨域")
|
||||
private String isCrossDomain;
|
||||
|
||||
@ApiModelProperty("跨域联盟城市")
|
||||
private String crossDomainCities;
|
||||
|
||||
@ApiModelProperty("是否已报名 0-未报名 1-已报名")
|
||||
private Integer isSignUp;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -4,8 +4,10 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.ruoyi.cms.domain.OutdoorFairBooth;
|
||||
import org.apache.ibatis.annotations.Delete;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public interface OutdoorFairBoothMapper extends BaseMapper<OutdoorFairBooth>
|
||||
{
|
||||
@@ -21,4 +23,18 @@ public interface OutdoorFairBoothMapper extends BaseMapper<OutdoorFairBooth>
|
||||
"</script>"
|
||||
})
|
||||
int physicalDeleteByFairIdAndIds(@Param("fairId") Long fairId, @Param("ids") List<Long> ids);
|
||||
|
||||
/** 批量统计招聘会实际展位图数量,区别于招聘会配置的展位容量。 */
|
||||
@Select({
|
||||
"<script>",
|
||||
"SELECT fair_id AS \"fairId\", COUNT(*) AS \"boothMapCount\"",
|
||||
"FROM cms_outdoor_fair_booth",
|
||||
"WHERE fair_id IN",
|
||||
"<foreach collection='fairIds' item='fairId' open='(' separator=',' close=')'>",
|
||||
"#{fairId}",
|
||||
"</foreach>",
|
||||
"GROUP BY fair_id",
|
||||
"</script>"
|
||||
})
|
||||
List<Map<String, Object>> countBoothsByFairIds(@Param("fairIds") List<Long> fairIds);
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
@@ -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-MM;null代表至今在职
|
||||
*/
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
|
||||
@@ -40,13 +40,21 @@
|
||||
<result property="jobFairId" column="job_fair_id"/>
|
||||
<result property="jobFairTitle" column="job_fair_title"/>
|
||||
<result property="jobFairAddress" column="job_fair_address"/>
|
||||
<result property="jobFairHostUnit" column="job_fair_host_unit"/>
|
||||
<result property="jobFairHelpUnit" column="job_fair_help_unit"/>
|
||||
<result property="jobFairOrganizeUnit" column="job_fair_organize_unit"/>
|
||||
<result property="jobFairPhone" column="job_fair_phone"/>
|
||||
<result property="jobFairIntroduction" column="job_fair_introduction"/>
|
||||
<result property="jobFairStartTime" column="job_fair_start_time"/>
|
||||
<result property="jobFairEndTime" column="job_fair_end_time"/>
|
||||
<result property="jobFairSignUpStartTime" column="job_fair_sign_up_start_time"/>
|
||||
<result property="jobFairSignUpEndTime" column="job_fair_sign_up_end_time"/>
|
||||
<result property="jobFairType" column="job_fair_type"/>
|
||||
<result property="jobFairRegionType" column="job_fair_region_type"/>
|
||||
<result property="latitude" column="latitude"/>
|
||||
<result property="longitude" column="longitude"/>
|
||||
<result property="isCrossDomain" column="is_cross_domain"/>
|
||||
<result property="crossDomainCities" column="cross_domain_cities"/>
|
||||
</resultMap>
|
||||
|
||||
<resultMap type="com.ruoyi.cms.domain.rc.PublicJobFairCompanyVO" id="CompanyVOResult">
|
||||
@@ -109,8 +117,12 @@
|
||||
</select>
|
||||
|
||||
<select id="selectPublicJobFairDetailById" resultMap="DetailResult">
|
||||
select job_fair_id, job_fair_title, job_fair_address, job_fair_introduction,
|
||||
job_fair_start_time, job_fair_end_time, job_fair_type, job_fair_region_type, latitude, longitude
|
||||
select job_fair_id, job_fair_title, job_fair_address,
|
||||
job_fair_host_unit, job_fair_help_unit, job_fair_organize_unit, job_fair_phone,
|
||||
job_fair_introduction, job_fair_start_time, job_fair_end_time,
|
||||
job_fair_sign_up_start_time, job_fair_sign_up_end_time,
|
||||
job_fair_type, job_fair_region_type, latitude, longitude,
|
||||
is_cross_domain, cross_domain_cities
|
||||
from public_job_fair
|
||||
where job_fair_id = #{jobFairId} and del_flag = '0'
|
||||
</select>
|
||||
|
||||
Reference in New Issue
Block a user