Merge remote-tracking branch 'origin/main'

This commit is contained in:
戈经莹
2026-07-30 19:07:48 +08:00
24 changed files with 1262 additions and 7 deletions

View File

@@ -0,0 +1,78 @@
package com.ruoyi.cms.controller.cms;
import cn.hutool.core.collection.CollUtil;
import com.ruoyi.cms.domain.JobExcelImportRecord;
import com.ruoyi.cms.service.IJobService;
import com.ruoyi.cms.service.JobExcelImportRecordService;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.util.List;
/**
* 石河子岗位数据入库监测记录Controller
*/
@RestController
@RequestMapping("/cms/jobImportRecord")
@Api(value = "后台:石河子岗位数据入库监测记录")
public class JobExcelImportRecordController extends BaseController {
@Autowired
private JobExcelImportRecordService jobExcelImportRecordService;
@Autowired
private IJobService jobService;
/**
* 查询列表
*/
@PreAuthorize("@ss.hasPermi('cms:jobImportRecord:list')")
@GetMapping("/list")
public TableDataInfo list(JobExcelImportRecord shzJobExcelImportRecord) {
startPage();
List<JobExcelImportRecord> list = jobExcelImportRecordService.selectShzJobExcelImportRecordList(shzJobExcelImportRecord);
return getDataTable(list);
}
/**
* 通用上传请求(单个)
*/
@PostMapping("/shzLocalUploadFile")
@PreAuthorize("@ss.hasPermi('cms:jobImportRecord:upload')")
@ApiOperation("石河子本地岗位上传")
public AjaxResult upload(@RequestParam("file") MultipartFile file) throws Exception {
if (file.isEmpty()) {
return AjaxResult.error("上传文件不能为空");
}
String fileName = file.getOriginalFilename();
if (fileName == null || !fileName.endsWith(".xlsx") && !fileName.endsWith(".xls")) {
return AjaxResult.error("请上传Excel格式的文件");
}
List<Long> effectIds=jobExcelImportRecordService.uploadFile(file);
if (CollUtil.isNotEmpty(effectIds)) {
this.asyncFillLonLat(effectIds);
}
return success();
}
/**
* 批量更新坐标
* @param jobIdList
*/
@Async
public void asyncFillLonLat(List<Long> jobIdList) {
try {
jobService.updateLonToByIds(jobIdList);
} catch (Exception e) {
e.printStackTrace();
}
}
}

View File

@@ -2,6 +2,7 @@ package com.ruoyi.cms.domain;
import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnore;
import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.core.domain.entity.Company; import com.ruoyi.common.core.domain.entity.Company;
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModelProperty;
import lombok.Data; import lombok.Data;
@@ -176,4 +177,13 @@ public class ESJobDocument
@ApiModelProperty("岗位特征行政、后勤、管理、技术、销售等字典job_feature添加") @ApiModelProperty("岗位特征行政、后勤、管理、技术、销售等字典job_feature添加")
private String jobFeature; private String jobFeature;
@Excel(name = "专业要求")
private String majorRequire;
@ApiModelProperty("工作性质")
private String workNature;
@ApiModelProperty("薪酬类型")
private String salaryType;
} }

View File

@@ -257,6 +257,15 @@ public class Job extends BaseEntity
@ApiModelProperty("岗位特征行政、后勤、管理、技术、销售等字典job_feature添加") @ApiModelProperty("岗位特征行政、后勤、管理、技术、销售等字典job_feature添加")
private String jobFeature; private String jobFeature;
@Excel(name = "专业要求")
private String majorRequire;
@ApiModelProperty("工作性质")
private String workNature;
@ApiModelProperty("薪酬类型")
private String salaryType;
@TableField(exist = false) @TableField(exist = false)
@ApiModelProperty("户外招聘会岗位审核状态") @ApiModelProperty("户外招聘会岗位审核状态")
private String fairReviewStatus; private String fairReviewStatus;

View File

@@ -0,0 +1,51 @@
package com.ruoyi.cms.domain;
import com.baomidou.mybatisplus.annotation.TableName;
import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.core.domain.BaseEntity;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.Date;
/**
* 石河子岗位数据入库监测记录 shz.job_excel_import_record
*/
@Data
@ApiModel("石河子岗位数据入库监测记录")
@TableName("job_excel_import_record")
public class JobExcelImportRecord extends BaseEntity {
private static final long serialVersionUID = 1L;
/** 监测主键ID */
@Excel(name = "监测主键ID")
@ApiModelProperty("监测主键ID")
private String detectionId;
/** 原始文件名称 */
@Excel(name = "原始文件名称")
@ApiModelProperty("原始文件名称")
private String fileName;
/** 入库数量 */
@Excel(name = "入库数量")
@ApiModelProperty("入库数量")
private Integer storageNumber;
/** 入库结果简述 */
@Excel(name = "入库结果简述")
@ApiModelProperty("入库结果简述")
private String storageResult;
/** 入库详情 */
@Excel(name = "入库详情")
@ApiModelProperty("入库详情")
private String storageDetail;
/** 失败原因 */
@Excel(name = "失败原因")
@ApiModelProperty("失败原因")
private String failedReason;
}

View File

@@ -0,0 +1,146 @@
package com.ruoyi.cms.domain.vo;
import com.alibaba.excel.annotation.ExcelProperty;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.ruoyi.cms.domain.JobContact;
import com.ruoyi.cms.util.excel.*;
import com.ruoyi.common.annotation.Excel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.Date;
import java.util.List;
/**
* 石河子本地导入岗位对象 job
*/
@Data
public class JobShzLocalExcelVo
{
@ExcelProperty(value = "序号", index = 0)
@Excel(name = "序号")
@ApiModelProperty("序号")
private String xh;
@ExcelProperty(value = "所属行业", index = 1)
@Excel(name = "所属行业")
@ApiModelProperty("所属行业")
private String industry;
@ExcelProperty(value = "单位名称", index = 2)
@Excel(name = "单位名称")
@ApiModelProperty("单位名称")
private String companyName;
@ExcelProperty(value = "统一社会信用代码", index = 3)
@ApiModelProperty("统一社会信用代码")
private String code;
@ExcelProperty(value = "单位类型", index = 4)
@ApiModelProperty("单位类型")
private String companyNature;
@ExcelProperty(value = "人员规模", index = 5)
@ApiModelProperty("人员规模")
private String scale;
@ExcelProperty(value = "工作地区", index = 6)
@ApiModelProperty("工作地区")
private String jobAddress;
@ExcelProperty(value = "岗位工种名称", index =7)
@Excel(name = "岗位工种名称")
@ApiModelProperty("岗位工种名称")
private String jobTitle;
@ExcelProperty(value = "招聘人数", index = 8,converter = VacancyLongConverter.class)
@Excel(name = "招聘人数")
@ApiModelProperty("招聘人数")
private Long vacancies;
@ExcelProperty(value = "任职要求", index = 9)
@ApiModelProperty("任职要求")
private String description;
@Excel(name = "学历要求 对应字典education")
@ExcelProperty(value = "任职要求", index = 10)
@ApiModelProperty("学历要求 对应字典education")
private String education;
@ExcelProperty(value = "工作性质", index = 11)
@ApiModelProperty("工作性质")
private String workNature;
@ExcelProperty(value = "薪酬类型", index = 12)
@ApiModelProperty("薪酬类型")
private String salaryType;
@ExcelProperty(value = "最小薪资", index = 13)
@Excel(name = "最小薪资", readConverterExp = "元=")
@ApiModelProperty("最小薪资(元)")
private Long minSalary;
@ExcelProperty(value = "最大薪资", index = 14)
@Excel(name = "最大薪资", readConverterExp = "元=")
@ApiModelProperty("最大薪资(元)")
private Long maxSalary;
@ExcelProperty(value = "工作经验", index = 15)
@Excel(name = "工作经验要求 对应字典experience")
@ApiModelProperty("工作经验要求 对应字典experience")
private String experience;
@ExcelProperty(value = "专业要求", index = 16)
@Excel(name = "专业要求")
private String majorRequire;
@ExcelProperty(value = "联系人对象", index = 17, converter = ContactParseConverter.class)
private ContactParseResult contactParseResult;
@ExcelProperty(value = "邮箱", index = 18)
private String email;
@ExcelProperty(value = "岗位收集人", index = 19)
@ApiModelProperty("岗位收集人")
private String gwsjr;
@ExcelProperty(value = "需求月份", index = 20,converter = PostingDateConverter.class)
@JsonFormat(pattern = "yyyy-MM-dd")
@ApiModelProperty("发布时间")
private Date postingDate;
@ExcelProperty(value = "经办站点", index = 21)
@ApiModelProperty("数据来源/经办站点")
private String dataSource;
@ExcelProperty(value = "联系人")
@ApiModelProperty("联系人")
private String contactPerson;
@ExcelProperty(value = "联系人电话")
@ApiModelProperty("联系人电话")
private String contactPersonPhone;
@ExcelProperty(value = "岗位区划")
@Excel(name = "岗位区划")
@ApiModelProperty("岗位区划")
private String jobLocation;
@ExcelProperty(value = "岗位类型")
@ApiModelProperty("岗位类型 0疆内 1疆外")
private String jobType;
@ExcelProperty(value = "类型")
@ApiModelProperty("类型 0常规岗位 1就业见习岗位 2实习实训岗位 3社区实践岗位 4零工 对应字段字典position_type")
private String type;
@ApiModelProperty("是否发布 0未发布 1发布")
private Integer isPublish;
@ApiModelProperty("工作地点区县字典代码")
private Integer jobLocationAreaCode;
@ApiModelProperty("联系人列表")
private List<JobContact> jobContacts;
}

View File

@@ -66,4 +66,10 @@ public interface AppNoticeMapper extends BaseMapper<AppNotice>
public int deleteNoticeByIds(Long[] noticeIds); public int deleteNoticeByIds(Long[] noticeIds);
List<Job> recommend(@Param("jobTitle")String jobTitle,@Param("userId") Long userId); List<Job> recommend(@Param("jobTitle")String jobTitle,@Param("userId") Long userId);
/**
* 按身份证号查询人才服务系统推送的有效岗位。
*/
List<Job> recommendByIdNumber(@Param("jobTitle") String jobTitle,
@Param("idNumber") String idNumber);
} }

View File

@@ -41,4 +41,8 @@ public interface CompanyMapper extends BaseMapper<Company>
/** 查询企业未参加的已结束户外招聘会。 */ /** 查询企业未参加的已结束户外招聘会。 */
List<CompanyMissedOutdoorFairVO> selectMissedOutdoorFairList(@Param("companyId") Long companyId); List<CompanyMissedOutdoorFairVO> selectMissedOutdoorFairList(@Param("companyId") Long companyId);
public List<Company> selectCompanyCleanList(CompanySearch company);
List<Company> selectCompanyByNameList(@Param("nameList") List<String> list);
} }

View File

@@ -0,0 +1,19 @@
package com.ruoyi.cms.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.ruoyi.cms.domain.JobExcelImportRecord;
import java.util.List;
/**
* 石河子岗位数据入库监测记录Mapper
*/
public interface JobExcelImportRecordMapper extends BaseMapper<JobExcelImportRecord> {
/**
* 查询石河子岗位数据入库监测记录列表
*
* @param shzJobExcelImportRecord 石河子岗位数据入库监测记录
* @return 石河子岗位数据入库监测记录集合
*/
List<JobExcelImportRecord> selectShzJobExcelImportRecordList(JobExcelImportRecord shzJobExcelImportRecord);
}

View File

@@ -84,4 +84,7 @@ public interface JobMapper extends BaseMapper<Job> {
//根据企业id批量下架架岗位 //根据企业id批量下架架岗位
public void updateBatchDownStatus(@Param("companyId") Long companyId); public void updateBatchDownStatus(@Param("companyId") Long companyId);
//根据名称查询企业
List<Job> selectJobByMatchKeyList(@Param("keyList") List<String> list);
} }

View File

@@ -122,4 +122,6 @@ public interface IJobService
public int jobDown(Long jobId); public int jobDown(Long jobId);
public int jobUp(Long jobId); public int jobUp(Long jobId);
void updateLonToByIds(List<Long> ids);
} }

View File

@@ -0,0 +1,22 @@
package com.ruoyi.cms.service;
import com.ruoyi.cms.domain.JobExcelImportRecord;
import org.springframework.web.multipart.MultipartFile;
import java.util.List;
/**
* 石河子岗位数据入库监测记录Service接口
*/
public interface JobExcelImportRecordService {
/**
* 查询石河子岗位数据入库监测记录列表
*
* @param jobExcelImportRecord 石河子岗位数据入库监测记录
* @return 石河子岗位数据入库监测记录集合
*/
List<JobExcelImportRecord> selectShzJobExcelImportRecordList(JobExcelImportRecord jobExcelImportRecord);
List<Long> uploadFile(MultipartFile file) throws Exception;
}

View File

@@ -8,6 +8,7 @@ import com.ruoyi.cms.mapper.*;
import com.ruoyi.cms.service.IAppNoticeService; import com.ruoyi.cms.service.IAppNoticeService;
import com.ruoyi.cms.util.notice.NoticeUtils; import com.ruoyi.cms.util.notice.NoticeUtils;
import com.ruoyi.cms.util.StringUtil; import com.ruoyi.cms.util.StringUtil;
import com.ruoyi.cms.util.RoleUtils;
import com.ruoyi.common.core.domain.entity.AppUser; import com.ruoyi.common.core.domain.entity.AppUser;
import com.ruoyi.common.utils.SiteSecurityUtils; import com.ruoyi.common.utils.SiteSecurityUtils;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@@ -164,6 +165,13 @@ public class AppNoticeServiceImpl implements IAppNoticeService
@Override @Override
public List<Job> recommend(String jobTitle) { public List<Job> recommend(String jobTitle) {
String idNumber = RoleUtils.getAppCurrentUseridCard();
if (idNumber != null && !idNumber.trim().isEmpty()) {
List<Job> pushedJobs = appNoticeMapper.recommendByIdNumber(jobTitle, idNumber);
if (!pushedJobs.isEmpty()) {
return pushedJobs;
}
}
return appNoticeMapper.recommend(jobTitle,SiteSecurityUtils.getUserId()); return appNoticeMapper.recommend(jobTitle,SiteSecurityUtils.getUserId());
} }
@@ -252,4 +260,3 @@ public class AppNoticeServiceImpl implements IAppNoticeService
return t; return t;
} }
} }

View File

@@ -0,0 +1,294 @@
package com.ruoyi.cms.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.file.FileNameUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.enums.CellExtraTypeEnum;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.cms.domain.BussinessDictData;
import com.ruoyi.cms.domain.Job;
import com.ruoyi.cms.domain.JobContact;
import com.ruoyi.cms.domain.JobExcelImportRecord;
import com.ruoyi.cms.domain.query.CompanySearch;
import com.ruoyi.cms.domain.vo.ContactParseResult;
import com.ruoyi.cms.domain.vo.JobShzLocalExcelVo;
import com.ruoyi.cms.mapper.CompanyMapper;
import com.ruoyi.cms.mapper.JobExcelImportRecordMapper;
import com.ruoyi.cms.mapper.JobMapper;
import com.ruoyi.cms.service.*;
import com.ruoyi.cms.util.excel.JobShzLocalExcelListener;
import com.ruoyi.cms.util.excel.UpExcelDictUtil;
import com.ruoyi.common.core.domain.entity.Company;
import com.ruoyi.common.core.domain.entity.Industry;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.uuid.IdUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.io.InputStream;
import java.util.*;
import java.util.stream.Collectors;
/**
* 石河子岗位数据入库监测记录Service实现
*/
@Service
public class JobExcelImportRecordServiceImpl extends ServiceImpl<JobExcelImportRecordMapper, JobExcelImportRecord> implements JobExcelImportRecordService {
@Autowired
private JobExcelImportRecordMapper jobExcelImportRecordMapper;
@Autowired
private JobMapper jobMapper;
@Autowired
private CompanyMapper companyMapper;
@Autowired
private IBussinessDictTypeService iBussinessDictTypeService;
@Autowired
private IBussinessDictDataService iBussinessDictDataService;
@Autowired
private IIndustryService industryService;
@Autowired
private IJobService jobService;
@Override
public List<JobExcelImportRecord> selectShzJobExcelImportRecordList(JobExcelImportRecord jobExcelImportRecord) {
return jobExcelImportRecordMapper.selectShzJobExcelImportRecordList(jobExcelImportRecord);
}
@Override
public List<Long> uploadFile(MultipartFile file) throws Exception{
List<Long> allEffectJobIds = new ArrayList<>();
String originalName = file.getOriginalFilename();
String nameNoSuffix = FileNameUtil.getName(originalName);
//获取字典
List<BussinessDictData> workNaData = iBussinessDictTypeService.selectDictDataByType("work_nature");
List<BussinessDictData> majorRData = iBussinessDictTypeService.selectDictDataByType("major_require");
List<BussinessDictData> salarTypeData = iBussinessDictTypeService.selectDictDataByType("salary_type");
List<BussinessDictData> companyNatureData = iBussinessDictTypeService.selectDictDataByType("company_nature");
List<BussinessDictData> areaData = iBussinessDictTypeService.selectDictDataByType("area");
//查询第一级
List<Industry> industries=industryService.selectFirstLevelIndustryList();
JobExcelImportRecord jobExcelImportRecord=new JobExcelImportRecord();
jobExcelImportRecord.setFileName(nameNoSuffix);
String detectionId = IdUtils.fastSimpleUUID();
jobExcelImportRecord.setDetectionId(detectionId);
List<JobShzLocalExcelVo> validDataList;
try (InputStream inputStream = file.getInputStream()){
JobShzLocalExcelListener listener = new JobShzLocalExcelListener();
EasyExcel.read(inputStream, JobShzLocalExcelVo.class, listener).extraRead(CellExtraTypeEnum.MERGE).sheet(0).headRowNumber(2).doRead();
validDataList = listener.getValidDataList();
jobExcelImportRecord.setStorageNumber(validDataList.size());
}
if (CollUtil.isEmpty(validDataList)) {
jobExcelImportRecord.setStorageNumber(0);
jobExcelImportRecordMapper.insert(jobExcelImportRecord);
return new ArrayList<>();
}
jobExcelImportRecord.setStorageNumber(validDataList.size());
// 2.1 所有已存在企业 name -> companyId
Map<String, Long> companyNameIdMap = new HashMap<>();
List<Company> allCompany = companyMapper.selectCompanyCleanList(new CompanySearch());
if (CollUtil.isNotEmpty(allCompany)) {
allCompany.forEach(c -> companyNameIdMap.put(c.getName(), c.getCompanyId()));
}
// 收集当前批次所有匹配key只查需要的岗位避免全量企业岗位加载上万条
Set<String> matchKeySet = new HashSet<>();
for (JobShzLocalExcelVo vo : validDataList) {
String cName = vo.getCompanyName();
String title = vo.getJobTitle();
String key=buildFullMatchKey(cName,title,vo.getVacancies(),vo.getMinSalary(),vo.getMaxSalary());
matchKeySet.add(key);
}
List<String> targetKeyList = new ArrayList<>(matchKeySet);
// 精准查询当前批次需要对比的存量岗位
List<Job> existJobList = jobMapper.selectJobByMatchKeyList(targetKeyList);
Map<String, Job> existJobMap = new HashMap<>();
for (Job job : existJobList) {
String key=buildFullMatchKey(job.getCompanyName(),job.getJobTitle(),job.getVacancies(),job.getMinSalary(),job.getMaxSalary());
existJobMap.put(key, job);
}
// 本批计数器
List<Company> waitInsertCompany = new ArrayList<>();
List<Job> waitInsertJob = new ArrayList<>();
List<Job> waitUpdateJob = new ArrayList<>();
// 3. 批量容器 & 统计计数器
int addCompanyNum = 0;
int addJobNum = 0;
int updateJobNum = 0;
// 4. 循环解析每行Excel数据
for (JobShzLocalExcelVo excelVo : validDataList) {
Job job = new Job();
BeanUtil.copyProperties(excelVo, job);
// 岗位固定默认值
job.setIsPublish(1);
job.setView(0L);
job.setApplyNum(0);
job.setCreateBy(detectionId);
job.setJobLocation(job.getJobAddress());
job.setExperience("0");
job.setJobType("0");
job.setJobStatus("0");
job.setDataSource("5");
String companyName = excelVo.getCompanyName();
String creditCode = excelVo.getCode();
Long companyId = null;
// ========== 企业处理逻辑 ==========
if (StringUtils.isNotBlank(companyName)) {
if (companyNameIdMap.containsKey(companyName)) {
// 企业已存在
companyId = companyNameIdMap.get(companyName);
} else {
// 新增企业
Company newCompany = new Company();
newCompany.setCreateBy(detectionId);
newCompany.setCompanyStatus("0");
newCompany.setCode(creditCode);
newCompany.setName(companyName);
// 企业字典转换
newCompany.setIndustry(UpExcelDictUtil.getIndustry(industries, excelVo.getIndustry()));
String companyNature = iBussinessDictDataService.findCode(companyNatureData, excelVo.getCompanyNature());
newCompany.setCompanyNature(StringUtils.isNotBlank(companyNature) ? companyNature : "9");
String scaleKey = UpExcelDictUtil.KEY_TO_SCALE_KEY.get(excelVo.getScale());
newCompany.setScale(StringUtils.isNotBlank(scaleKey) ? scaleKey : "0");
waitInsertCompany.add(newCompany);
addCompanyNum++;
companyId = -1L; // 临时占位批量插入后回填真实ID
}
}
job.setCompanyId(companyId);
// ========== 岗位字典赋值 ==========
String eduKey = UpExcelDictUtil.KEY_TO_SCALE_KEY.get(excelVo.getEducation());
job.setEducation(StringUtils.isNotBlank(eduKey) ? eduKey : "-1");
String expKey = UpExcelDictUtil.KEY_TO_EXPERIENCE_KEY.get(excelVo.getExperience());
job.setExperience(StringUtils.isNotBlank(expKey) ? expKey : "0");
job.setWorkNature(iBussinessDictDataService.findCode(workNaData, excelVo.getWorkNature()));
job.setSalaryType(iBussinessDictDataService.findCode(salarTypeData, excelVo.getSalaryType()));
job.setMajorRequire(iBussinessDictDataService.findCode(majorRData, excelVo.getMajorRequire()));
job.setJobLocationAreaCode(UpExcelDictUtil.matchRegionCode(areaData, excelVo.getJobAddress()));
// ========== 联系人解析 ==========
List<JobContact> contactList = new ArrayList<>();
ContactParseResult parseResult = excelVo.getContactParseResult();
if (ObjectUtil.isNotNull(parseResult) && CollUtil.isNotEmpty(parseResult.getContactItemList())) {
parseResult.getContactItemList().stream()
.filter(item -> StringUtils.isNotBlank(StrUtil.trim(item.getPhone())))
.forEach(item -> {
JobContact contact = new JobContact();
contact.setContactPerson(companyName);
contact.setContactPersonPhone(StrUtil.trim(item.getPhone()));
contact.setRemark(item.getRemark());
contactList.add(contact);
});
}
if (CollUtil.isNotEmpty(contactList)) {
job.setJobContactList(contactList);
}
// ========== 判断岗位新增/更新兼容历史无companyId数据 ==========
String matchKey=buildFullMatchKey(excelVo.getCompanyName(), excelVo.getJobTitle(),excelVo.getVacancies(), excelVo.getMinSalary(), excelVo.getMaxSalary());
if (existJobMap.containsKey(matchKey)) {
// 命中存量岗位含历史无企业ID脏数据
Job oldJob = existJobMap.get(matchKey);
job.setJobId(oldJob.getJobId());
waitUpdateJob.add(job);
updateJobNum++;
} else {
// 全新岗位
waitInsertJob.add(job);
addJobNum++;
}
}
//批量入库
if (CollUtil.isNotEmpty(waitInsertCompany)) {
companyMapper.batchInsert(waitInsertCompany);
// 重新查询新增企业刷新name-id映射
List<String> newCompanyNames = waitInsertCompany.stream()
.map(Company::getName)
.collect(Collectors.toList());
List<Company> newInsertCompanies = companyMapper.selectCompanyByNameList(newCompanyNames);
newInsertCompanies.forEach(c -> companyNameIdMap.put(c.getName(), c.getCompanyId()));
// 给待新增岗位回填真实companyId
for (Job j : waitInsertJob) {
if (j.getCompanyId() != null && j.getCompanyId() == -1L) {
Long realCid = companyNameIdMap.get(j.getCompanyName());
j.setCompanyId(realCid);
}
}
// 给历史待更新岗位补全companyId存量数据标准化
for (Job j : waitUpdateJob) {
if (j.getCompanyId() == null && companyNameIdMap.containsKey(j.getCompanyName())) {
j.setCompanyId(companyNameIdMap.get(j.getCompanyName()));
}
}
}
//批量新增岗位
if (CollUtil.isNotEmpty(waitInsertJob)) {
jobMapper.batchInsert(waitInsertJob);
waitInsertJob.forEach(j -> allEffectJobIds.add(j.getJobId()));
}
//批量更新岗位
if (CollUtil.isNotEmpty(waitUpdateJob)) {
List<List<Job>> splitList = CollUtil.split(waitUpdateJob, 500);
for (List<Job> sub : splitList) {
sub.forEach(it -> {
it.setCreateBy(null);
it.setCreateTime(null);
it.setUpdateBy(detectionId);
jobMapper.updateById(it);
allEffectJobIds.add(it.getJobId());
}
);
}
}
//记录结果
String brief = String.format("共导入%d条数据新增企业%d家新增岗位%d条更新岗位%d条",
jobExcelImportRecord.getStorageNumber(), addCompanyNum, addJobNum, updateJobNum);
jobExcelImportRecord.setStorageResult(brief);
// 入库详情
StringBuilder detailSb = new StringBuilder();
detailSb.append("【导入统计明细】\n");
detailSb.append("有效导入行数:").append(jobExcelImportRecord.getStorageNumber()).append("\n");
detailSb.append("新增企业:").append(addCompanyNum).append("\n");
detailSb.append("新增岗位:").append(addJobNum).append("\n");
detailSb.append("更新岗位:").append(updateJobNum).append("");
jobExcelImportRecord.setStorageDetail(detailSb.toString());
jobExcelImportRecordMapper.insert(jobExcelImportRecord);
return allEffectJobIds;
}
/**
* 获取key
* @param companyName
* @param jobTitle
* @param vacancies
* @param minSalary
* @param maxSalary
* @return
*/
private String buildFullMatchKey(String companyName, String jobTitle, Long vacancies, Long minSalary, Long maxSalary) {
String vacStr = vacancies == null ? "" : vacancies.toString();
String minSalStr = minSalary == null ? "" : minSalary.toString();
String maxSalStr = maxSalary == null ? "" : maxSalary.toString();
return companyName + "|" + jobTitle + "|" + vacStr + "|" + minSalStr + "|" + maxSalStr;
}
}

View File

@@ -1,5 +1,6 @@
package com.ruoyi.cms.service.impl; package com.ruoyi.cms.service.impl;
import cn.hutool.core.collection.CollUtil;
import com.alibaba.fastjson2.JSONArray; import com.alibaba.fastjson2.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
@@ -187,6 +188,61 @@ public class JobServiceImpl extends ServiceImpl<JobMapper,Job> implements IJobSe
System.out.println("工作地址经纬度更新完成,共处理 " + jobs.size() + " 条记录"); System.out.println("工作地址经纬度更新完成,共处理 " + jobs.size() + " 条记录");
} }
/**
* 更新工作地址的经纬度信息
*/
@Override
public void updateLonToByIds(List<Long> ids) {
System.out.println("开始执行工作地址经纬度更新...");
// 1. 查询需要更新经纬度的工作地址
List<Job> jobs = jobMapper.selectList(
Wrappers.<Job>lambdaQuery()
.in(Job::getJobId, ids)
.and(wrapper -> wrapper.isNull(Job::getLongitude).or().eq(Job::getLongitude, BigDecimal.ZERO))
// 限制每次处理10条
);
if (jobs.isEmpty()) {
System.out.println("没有需要更新经纬度的工作地址");
return;
}
// 2. 遍历处理每个工作地址
for (Job job : jobs) {
try {
System.out.println("\n正在处理工作ID: " + job.getJobId() +
", 地址: " + job.getJobLocation());
// 调用高德API获取经纬度添加适当延迟
TimeUnit.MILLISECONDS.sleep(500);
Map<String, BigDecimal> coordinates = getCoordinates(job.getJobLocation(), "石河子市");
if (coordinates != null) {
// 3. 更新工作记录的经纬度
job.setLongitude(coordinates.get("lng"));
job.setLatitude(coordinates.get("lat"));
// 使用MyBatis Plus的update方法
jobMapper.updateById(job);
System.out.println("成功更新工作ID: " + job.getJobId() +
" 的经纬度 -> 经度: " + job.getLongitude() +
", 纬度: " + job.getLatitude());
} else {
System.out.println("无法获取工作地址的经纬度: " + job.getJobLocation());
jobMapper.updateById(job);
}
} catch (Exception e) {
System.err.println("处理工作ID " + job.getJobId() + " 时出错: " + e.getMessage());
}
}
System.out.println("工作地址经纬度更新完成,共处理 " + jobs.size() + " 条记录");
if (CollUtil.isNotEmpty(jobs)) {
iesJobSearchService.resetTextCache();
}
}
/** /**
* 调用高德地图API获取地址的经纬度并返回BigDecimal * 调用高德地图API获取地址的经纬度并返回BigDecimal
*/ */

View File

@@ -1,5 +1,6 @@
package com.ruoyi.cms.service.policy.impl; package com.ruoyi.cms.service.policy.impl;
import cn.hutool.core.util.StrUtil;
import com.github.pagehelper.PageHelper; import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo; import com.github.pagehelper.PageInfo;
import com.ruoyi.cms.domain.policy.PolicyInfo; import com.ruoyi.cms.domain.policy.PolicyInfo;
@@ -67,8 +68,10 @@ public class PolicyInfoServiceImpl implements IPolicyInfoService {
@Override @Override
public PolicyInfo getDetail(Long id) { public PolicyInfo getDetail(Long id) {
PolicyInfo policyInfo = policyInfoMapper.selectPolicyInfoById(id); PolicyInfo policyInfo = policyInfoMapper.selectPolicyInfoById(id);
Industry industry = industryService.selectIndustryByIndustryId(Long.valueOf(policyInfo.getIndustryBigType())); if(StrUtil.isNotEmpty(policyInfo.getIndustryBigType())){
policyInfo.setIndustryBigTypeName(industry.getIndustryName()); Industry industry = industryService.selectIndustryByIndustryId(Long.valueOf(policyInfo.getIndustryBigType()));
policyInfo.setIndustryBigTypeName(industry.getIndustryName());
}
return policyInfo; return policyInfo;
} }

View File

@@ -59,7 +59,7 @@ public class RoleUtils {
throw new IllegalArgumentException("用户信息为空,无法获取身份证号"); // 用户信息为空仍抛异常,避免空指针 throw new IllegalArgumentException("用户信息为空,无法获取身份证号"); // 用户信息为空仍抛异常,避免空指针
} }
if ("0".equals(appUser.getIsCompanyUser())) { if (StringUtil.IS_JOB_REQUEST_USER.equals(appUser.getIsCompanyUser())) {
return appUser.getIdCard(); return appUser.getIdCard();
} else { } else {
return null; return null;

View File

@@ -0,0 +1,161 @@
package com.ruoyi.cms.util.excel;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.enums.CellExtraTypeEnum;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.exception.ExcelDataConvertException;
import com.alibaba.excel.metadata.CellExtra;
import com.alibaba.excel.metadata.data.ReadCellData;
import com.ruoyi.cms.domain.JobContact;
import com.ruoyi.cms.domain.vo.*;
import com.ruoyi.cms.util.StringUtil;
import lombok.Getter;
import org.apache.commons.lang3.StringUtils;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 企业岗位excel监听
*/
@Getter
public class JobShzLocalExcelListener extends AnalysisEventListener<JobShzLocalExcelVo> {
private final List<JobShzLocalExcelVo> validDataList = new ArrayList<>();
private final List<CellExtra> mergeCellList = new ArrayList<>();
private final Map<Integer, Field> columnFieldMap = new HashMap<>();
private String columnErrorMsg;
public JobShzLocalExcelListener() {
initColumnFieldMap();
}
@Override
public void invokeHead(Map<Integer, ReadCellData<?>> headMap, AnalysisContext context) {
}
@Override
public void extra(CellExtra extra, AnalysisContext context) {
if (extra.getType() == CellExtraTypeEnum.MERGE) {
mergeCellList.add(extra);
}
}
@Override
public void invoke(JobShzLocalExcelVo jobExcelVo, AnalysisContext analysisContext) {
//处理联系方式
ContactParseResult contactResult = jobExcelVo.getContactParseResult();
if (contactResult == null) {
contactResult = new ContactParseResult();
contactResult.setRawText("");
}
// 遍历拆分好的【联系人+号码】,可单独入库
List<JobContact> jobContacts=new ArrayList<>();
for (ContactUploadItem item : contactResult.getContactItemList()) {
JobContact jobContact=new JobContact();
if(StringUtils.isNotBlank(item.getPhone().trim())){
String name = item.getName();
String phone = item.getPhone();
String remark = item.getRemark();
jobContact.setContactPerson(name);
jobContact.setContactPersonPhone(phone);
jobContact.setRemark(remark);
jobContacts.add(jobContact);
}
}
if(!jobContacts.isEmpty()){
jobExcelVo.setJobContacts(jobContacts);
}
//数据来源
jobExcelVo.setDataSource(StringUtil.DATA_SOURCE_LOCAL);
validDataList.add(jobExcelVo);
}
@Override
public void doAfterAllAnalysed(AnalysisContext analysisContext) {
fillMergedCellData(analysisContext);
}
/**
* 填充合并单元格空值,实现拆分效果
*/
private void fillMergedCellData(AnalysisContext context) {
int headRowNum = context.readSheetHolder().getHeadRowNumber();
if (columnFieldMap.isEmpty()) {
return;
}
for (CellExtra merge : mergeCellList) {
int firstRow = merge.getFirstRowIndex();
int lastRow = merge.getLastRowIndex();
int firstCol = merge.getFirstColumnIndex();
// 跳过表头
if (firstRow < headRowNum) {
continue;
}
Field field = columnFieldMap.get(firstCol);
if (field == null) {
continue;
}
try {
int firstDataIndex = firstRow - headRowNum;
if (firstDataIndex >= validDataList.size()) {
continue;
}
// 获取合并首行的值
Object mergeValue = field.get(validDataList.get(firstDataIndex));
// 给合并区域所有行赋值
for (int row = firstRow + 1; row <= lastRow; row++) {
int dataIndex = row - headRowNum;
if (dataIndex >= validDataList.size()) {
continue;
}
field.set(validDataList.get(dataIndex), mergeValue);
}
} catch (Exception e) {
columnErrorMsg = "合并单元格填充失败:" + e.getMessage();
}
}
}
/**
* 扫描VO实体 @ExcelProperty(index) 构建列-字段映射
*/
private void initColumnFieldMap() {
Class<JobLocalExcelVo> clazz = JobLocalExcelVo.class;
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
ExcelProperty excelProp = field.getAnnotation(ExcelProperty.class);
if (excelProp == null || excelProp.index() < 0) {
continue;
}
field.setAccessible(true);
columnFieldMap.put(excelProp.index(), field);
}
}
@Override
public void onException(Exception exception, AnalysisContext context) {
if (exception instanceof ExcelDataConvertException) {
ExcelDataConvertException e = (ExcelDataConvertException) exception;
int realExcelRow = e.getRowIndex() + 3;
int colNum = e.getColumnIndex() + 1;
String cellText = e.getCellData().getStringValue();
System.out.println("Excel导入失败实际行号" + realExcelRow + ",列号" + colNum + ",单元格内容【" + cellText + "");
}
}
public boolean hasColumnError() {
return StringUtils.isNotBlank(columnErrorMsg);
}
}

View File

@@ -0,0 +1,136 @@
package com.ruoyi.cms.util.excel;
import cn.hutool.core.util.StrUtil;
import com.ruoyi.cms.domain.BussinessDictData;
import com.ruoyi.common.core.domain.entity.Industry;
import java.util.*;
public class UpExcelDictUtil {
/**
* 工作经验集合
* 1,应届毕业生
* 11,10年以上
* 2,1年
* 20,20年以上
* 3,2年
* 4,3-4年
* 6,5-7年
* 80,在读生
* 9,8-9年
* 90,不限
*/
public static final Map<String, String> KEY_TO_EXPERIENCE_KEY = new HashMap<>();
/**
* 学历
* 11博士
* 14硕士
* 21本科
* 31专科
* 41中专
* 61高中
* 71初中
* 81小学
* 90学历不限
*/
public static final Map<String, String> KEY_TO_EDUCATION_KEY = new HashMap<>();
/**
* 规模
* 1_3000人以上
* 2_1000--2999人
* 3_500--999人
* 4_100--499人
* 5_10--99人
* 6_10人以下
* 9_其他
*/
public static final Map<String, String> KEY_TO_SCALE_KEY = new HashMap<>();
//默认石河子市
private static final Integer SHIHEZI_DEFAULT_CODE = 0;
static {
//工作经验
KEY_TO_EXPERIENCE_KEY.put("应届毕业生","2");
KEY_TO_EXPERIENCE_KEY.put("在读生","10");
KEY_TO_EXPERIENCE_KEY.put("1年","4");
KEY_TO_EXPERIENCE_KEY.put("2年","4");
KEY_TO_EXPERIENCE_KEY.put("3-4年","5");
KEY_TO_EXPERIENCE_KEY.put("5-7年","6");
KEY_TO_EXPERIENCE_KEY.put("8-9年","6");
KEY_TO_EXPERIENCE_KEY.put("10年以上","7");
KEY_TO_EXPERIENCE_KEY.put("20年以上","8");
KEY_TO_EXPERIENCE_KEY.put("不限","0");
//学历
KEY_TO_EDUCATION_KEY.put("博士","6");
KEY_TO_EDUCATION_KEY.put("硕士","5");
KEY_TO_EDUCATION_KEY.put("本科","4");
KEY_TO_EDUCATION_KEY.put("专科","3");
KEY_TO_EDUCATION_KEY.put("中专","1");
KEY_TO_EDUCATION_KEY.put("高中","2");
KEY_TO_EDUCATION_KEY.put("初中","1");
KEY_TO_EDUCATION_KEY.put("小学","0");
KEY_TO_EDUCATION_KEY.put("学历不限","-1");
//规模
KEY_TO_SCALE_KEY.put("3000人以上","6");
KEY_TO_SCALE_KEY.put("1000--2999人","6");
KEY_TO_SCALE_KEY.put("500--999人","5");
KEY_TO_SCALE_KEY.put("100--499人","3");
KEY_TO_SCALE_KEY.put("10--99人","2");
KEY_TO_SCALE_KEY.put("10人以下","1");
KEY_TO_SCALE_KEY.put("其他","0");
}
/**
* 获取行业
* @param industryList
* @param name
* @return
*/
public static String getIndustry(List<Industry> industryList,String name){
if (Objects.isNull(industryList) || StrUtil.isBlank(name)) {
return null;
}
String targetName = name.trim();
for(Industry industry:industryList){
String industryName = StrUtil.trim(industry.getIndustryName());
if(Objects.equals(industryName, targetName)){
return String.valueOf(industry.getIndustryId());
}
}
return null;
}
/**
* 获取区划
* @param dictDataList
* @param address
* @return
*/
public static Integer matchRegionCode(List<BussinessDictData> dictDataList, String address) {
// 空参数直接返回默认值
if (StrUtil.isBlank(address) || dictDataList == null || dictDataList.isEmpty()) {
return SHIHEZI_DEFAULT_CODE;
}
String addr = address.trim();
// 重点:按标签长度倒序,长关键词优先匹配,防止短词误命中
Optional<BussinessDictData> matchDict = dictDataList.stream()
.filter(d -> StrUtil.isNotBlank(d.getDictLabel()))
.sorted((o1, o2) -> Integer.compare(o2.getDictLabel().length(), o1.getDictLabel().length()))
.filter(d -> addr.contains(d.getDictLabel()))
.findFirst();
return matchDict.map(BussinessDictData::getDictValue).map(val -> {
try {
return Integer.valueOf(val);
} catch (NumberFormatException e) {
return null;
}
}).orElse(SHIHEZI_DEFAULT_CODE);
}
}

View File

@@ -21,7 +21,15 @@ public class VacancyLongConverter implements Converter<Long> {
*/ */
@Override @Override
public Long convertToJavaData(ReadCellData<?> cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { public Long convertToJavaData(ReadCellData<?> cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) {
String source = cellData.getStringValue(); String source = null;
CellDataTypeEnum cellType = cellData.getType();
if (CellDataTypeEnum.NUMBER.equals(cellType)) {
source = cellData.getNumberValue().toPlainString();
} else if (CellDataTypeEnum.STRING.equals(cellType)) {
source = cellData.getStringValue();
} else if (CellDataTypeEnum.BOOLEAN.equals(cellType)) {
source = cellData.getBooleanValue().toString();
}
return extractVacancyNum(source); return extractVacancyNum(source);
} }

View File

@@ -52,6 +52,57 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</if> </if>
</select> </select>
<select id="recommendByIdNumber" resultType="com.ruoyi.cms.domain.Job">
SELECT
j.job_id AS jobId,
j.job_title AS jobTitle,
j.min_salary AS minSalary,
j.max_salary AS maxSalary,
j.salary_composition AS salaryComposition,
j.welfare_benefits AS welfareBenefits,
j.work_schedule AS workSchedule,
j.education AS education,
j.experience AS experience,
j.company_name AS companyName,
j.job_location AS jobLocation,
j.job_location_area_code AS jobLocationAreaCode,
j.posting_date AS postingDate,
j.vacancies AS vacancies,
j.latitude AS latitude,
j.longitude AS longitude,
j."view" AS view,
j.company_id AS companyId,
j.is_hot AS isHot,
j.is_urgent AS isUrgent,
j.apply_num AS applyNum,
j.description AS description,
j.is_publish AS isPublish,
j.data_source AS dataSource,
j.job_url AS jobUrl,
j.row_id AS rowId,
j.job_category AS jobCategory,
j.is_explain AS isExplain,
j.explain_url AS explainUrl,
j.cover AS cover,
j.job_type AS jobType,
j.type AS type,
j.job_address AS jobAddress,
j.review_status AS reviewStatus,
j.is_key_populations AS isKeyPopulations,
j.key_populations AS keyPopulations,
j.job_feature AS jobFeature
FROM shz.job_push_record AS r
INNER JOIN shz.job AS j ON j.job_id = r.job_id
WHERE r.id_number = #{idNumber}
AND r.is_push = 1
AND j.del_flag = '0'
AND j.is_publish = 1
<if test="jobTitle != null and jobTitle != ''">
AND j.job_category = #{jobTitle}
</if>
ORDER BY r.push_time DESC NULLS LAST, j.posting_date DESC NULLS LAST, j.job_id DESC
</select>
<insert id="insertNotice" parameterType="SysNotice"> <insert id="insertNotice" parameterType="SysNotice">
insert into app_notice ( insert into app_notice (
<if test="noticeTitle != null and noticeTitle != '' ">notice_title, </if> <if test="noticeTitle != null and noticeTitle != '' ">notice_title, </if>

View File

@@ -333,4 +333,75 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
ORDER BY f.end_time DESC, f.id DESC ORDER BY f.end_time DESC, f.id DESC
</select> </select>
<select id="selectCompanyCleanList" parameterType="CompanySearch" resultMap="baseCompanyResult">
<include refid="selectBaseCompanyVo" />
<where> cp.del_flag = '0'
<if test="name != null and name != ''"> and cp.name like concat('%', cast(#{name, jdbcType=VARCHAR} as varchar), '%')</if>
<if test="location != null and location != ''"> and cp.location = #{location}</if>
<include refid="companyIndustryFilter"/>
<if test="scale != null and scale != ''"> and cp.scale = #{scale}</if>
<if test="nature != null and nature != ''"> and cp.nature = #{nature}</if>
<if test="companyNature != null and companyNature != ''"> and cp.company_nature = #{companyNature}</if>
<if test="code != null and code != ''"> and cp.code = #{code}</if>
<if test="status != null and status != ''"> and cp.status = #{status}</if>
<if test="companyId != null and companyId != ''"> and cp.company_id = #{companyId}</if>
<if test="userId != null"> and cp.user_id = #{userId}</if>
<if test="isHrs != null and isHrs != ''"> and cp.is_hrs = #{isHrs}</if>
</where>
</select>
<sql id="selectBaseCompanyVo">
select company_id, name, location, industry, scale, del_flag, create_by, create_time, update_by, update_time, remark,code,description,nature,company_nature,total_recruitment,registered_address,contact_person,contact_person_phone,is_abnormal,not_pass_reason,status,case when status='2' then update_time else null end reject_time,is_imp_company,imp_company_type,enterprise_type,legal_person,legal_id_card,legal_phone,is_hrs from company cp
</sql>
<resultMap type="Company" id="baseCompanyResult">
<result property="companyId" column="company_id" />
<result property="name" column="name" />
<result property="location" column="location" />
<result property="industry" column="industry" />
<result property="scale" column="scale" />
<result property="code" column="code" />
<result property="delFlag" column="del_flag" />
<result property="createBy" column="create_by" />
<result property="createTime" column="create_time" />
<result property="updateBy" column="update_by" />
<result property="updateTime" column="update_time" />
<result property="remark" column="remark" />
<result property="description" column="description" />
<result property="nature" column="nature" />
<result property="companyNature" column="company_nature" />
<result property="totalRecruitment" column="total_recruitment" />
<result property="userId" column="user_id" />
<result property="businessLicenseUrl" column="business_license_url" />
<result property="idCardPictureUrl" column="id_card_picture_url" />
<result property="idCardPictureBackUrl" column="id_card_picture_back_url" />
<result property="powerOfAttorneyUrl" column="power_of_attorneyUrl" />
<result property="contactPerson" column="contact_person" />
<result property="contactPersonPhone" column="contact_person_phone" />
<result property="status" column="status" />
<result property="notPassReason" column="not_pass_reason" />
<result property="registeredAddress" column="registered_address" />
<result property="isAbnormal" column="is_abnormal" />
<result property="enterpriseType" column="enterprise_type" />
<result property="isImpCompany" column="is_imp_company" />
<result property="impCompanyType" column="imp_company_type" />
<result property="legalPerson" column="legal_person" />
<result property="legalIdCard" column="legal_id_card" />
<result property="legalPhone" column="legal_phone" />
<result property="companyStatus" column="company_status" />
<result property="isHrs" column="is_hrs" />
<result property="lcUserid" column="lc_userid" />
<result property="missedOutdoorFairCount" column="missed_outdoor_fair_count" />
</resultMap>
<select id="selectCompanyByNameList" resultMap="baseCompanyResult">
SELECT company_id,name,code,industry,company_nature,scale,company_status
FROM company
WHERE del_flag='0' and name IN
<foreach collection="nameList" item="name" open="(" separator="," close=")">
#{name}
</foreach>
</select>
</mapper> </mapper>

View File

@@ -0,0 +1,57 @@
<?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.JobExcelImportRecordMapper">
<resultMap type="com.ruoyi.cms.domain.JobExcelImportRecord" id="JobExcelImportRecordResult">
<result property="detectionId" column="detection_id" />
<result property="fileName" column="file_name" />
<result property="storageNumber" column="storage_number" />
<result property="storageResult" column="storage_result" />
<result property="storageDetail" column="storage_detail" />
<result property="failedReason" column="failed_reason" />
<result property="delFlag" column="del_flag" />
<result property="createBy" column="create_by" />
<result property="createTime" column="create_time" />
<result property="updateBy" column="update_by" />
<result property="updateTime" column="update_time" />
<result property="remark" column="remark" />
</resultMap>
<sql id="selectShzJobExcelImportRecordVo">
select detection_id,
file_name,
storage_number,
storage_result,
storage_detail,
failed_reason,
del_flag,
create_by,
create_time,
update_by,
update_time,
remark
from job_excel_import_record
</sql>
<select id="selectShzJobExcelImportRecordList" resultMap="JobExcelImportRecordResult">
<include refid="selectShzJobExcelImportRecordVo"/>
<where> del_flag='0'
<if test="fileName != null and fileName != ''">
and file_name like concat('%',#{fileName},'%')
</if>
<if test="storageResult != null and storageResult != ''">
and storage_result like concat('%',#{storageResult},'%')
</if>
<if test="params.beginTime != null and params.beginTime != ''">
and create_time &gt;= #{params.beginTime}
</if>
<if test="params.endTime != null and params.endTime != ''">
and create_time &lt;= #{params.endTime}
</if>
</where>
order by create_time desc
</select>
</mapper>

View File

@@ -228,6 +228,7 @@
<if test="applyNum != null "> and apply_num = #{applyNum}</if> <if test="applyNum != null "> and apply_num = #{applyNum}</if>
<if test="code != null "> and company_id in(select company_id from company where code=#{code})</if> <if test="code != null "> and company_id in(select company_id from company where code=#{code})</if>
<if test="jobStatus != null "> and job_status = #{jobStatus}</if> <if test="jobStatus != null "> and job_status = #{jobStatus}</if>
<if test="createBy != null and createBy!=null"> and create_by = #{createBy}</if>
<if test="compensation!=null "> <if test="compensation!=null ">
<if test="compensation==0 "> <if test="compensation==0 ">
and min_salary &lt; 1750 and min_salary &lt; 1750
@@ -465,4 +466,24 @@
update job set job_status='0', update_time = NOW() where del_flag='0' and company_id=#{companyId} and job_status='1' update job set job_status='0', update_time = NOW() where del_flag='0' and company_id=#{companyId} and job_status='1'
</update> </update>
<select id="selectJobByMatchKeyList" resultType="com.ruoyi.cms.domain.Job">
SELECT t2.* FROM job t2
WHERE t2.del_flag='0'
AND CONCAT(
COALESCE(t2.company_name, ''),
'|',
COALESCE(t2.job_title, ''),
'|',
COALESCE(CAST(t2.vacancies AS VARCHAR), ''),
'|',
COALESCE(CAST(t2.min_salary AS VARCHAR), ''),
'|',
COALESCE(CAST(t2.max_salary AS VARCHAR), '')
)
IN
<foreach collection="keyList" item="k" open="(" separator="," close=")">
#{k}
</foreach>
</select>
</mapper> </mapper>

View File

@@ -0,0 +1,40 @@
-- 执行状态:测试环境已执行
-- 测试环境test
-- 测试执行时间2026-07-30 10:06:47 +0800
-- 正式环境:未执行
-- 石河子智慧就业:人才服务岗位推送关联表。
-- 关联岗位 ID 与身份证号is_push=0 表示未推送is_push=1 表示已推送。
-- 可重复执行,不写入业务测试数据。
BEGIN;
SET LOCAL search_path = shz, public;
CREATE SEQUENCE IF NOT EXISTS job_push_record_id_seq
START WITH 1 INCREMENT BY 1 NO MINVALUE NO MAXVALUE CACHE 1;
CREATE TABLE IF NOT EXISTS job_push_record (
id BIGINT NOT NULL DEFAULT nextval('job_push_record_id_seq') PRIMARY KEY,
job_id BIGINT NOT NULL,
id_number VARCHAR(32) NOT NULL,
is_push SMALLINT NOT NULL DEFAULT 0,
push_time TIMESTAMP(0),
create_time TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP,
update_time TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP,
remark VARCHAR(500)
);
COMMENT ON TABLE job_push_record IS '人才服务岗位推送关联表';
COMMENT ON COLUMN job_push_record.job_id IS '石河子岗位 ID关联 job.job_id';
COMMENT ON COLUMN job_push_record.id_number IS '被推送人的身份证号';
COMMENT ON COLUMN job_push_record.is_push IS '是否已推送0未推送1已推送';
COMMENT ON COLUMN job_push_record.push_time IS '最近一次推送时间';
CREATE UNIQUE INDEX IF NOT EXISTS uk_job_push_record_job_id_number
ON job_push_record (job_id, id_number);
CREATE INDEX IF NOT EXISTS idx_job_push_record_id_number
ON job_push_record (id_number);
CREATE INDEX IF NOT EXISTS idx_job_push_record_is_push
ON job_push_record (is_push);
COMMIT;