feat: add recruitment fair participant export

This commit is contained in:
2026-07-23 18:35:18 +08:00
parent 3f11837e94
commit e558e70b45
7 changed files with 1013 additions and 0 deletions

View File

@@ -0,0 +1,47 @@
package com.ruoyi.cms.controller.cms;
import com.ruoyi.cms.domain.export.RecruitmentFairExportQuery;
import com.ruoyi.cms.service.RecruitmentFairExportService;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.enums.BusinessType;
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.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/** 线上/户外招聘会参会企业与岗位导出接口。 */
@RestController
@RequestMapping("/cms")
@Api(tags = "后台:招聘会参会数据导出")
public class RecruitmentFairExportController extends BaseController
{
@Autowired
private RecruitmentFairExportService exportService;
@ApiOperation("导出线上招聘会参会企业或岗位")
@PreAuthorize("@ss.hasPermi('cms:publicJobFair:export')")
@Log(title = "线上招聘会参会数据", businessType = BusinessType.EXPORT)
@PostMapping("/publicJobFair/export")
public void exportPublicJobFair(RecruitmentFairExportQuery query, HttpServletResponse response)
throws IOException
{
exportService.export(response, "online", query);
}
@ApiOperation("导出户外招聘会参会企业或岗位")
@PreAuthorize("@ss.hasPermi('cms:outdoorFair:export')")
@Log(title = "户外招聘会参会数据", businessType = BusinessType.EXPORT)
@PostMapping("/outdoor-fair/export")
public void exportOutdoorFair(RecruitmentFairExportQuery query, HttpServletResponse response)
throws IOException
{
exportService.export(response, "outdoor", query);
}
}

View File

@@ -0,0 +1,89 @@
package com.ruoyi.cms.domain.export;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.io.Serializable;
import java.util.Date;
/**
* 招聘会参会企业/岗位导出条件。
*
* <p>线上招聘会和户外招聘会共用这组条件,未被某一类招聘会使用的字段会被忽略。
* 时间条件使用闭区间,便于页面按“开始时间/结束时间”筛选整个招聘会。</p>
*/
@Data
@ApiModel("招聘会参会数据导出条件")
public class RecruitmentFairExportQuery implements Serializable
{
private static final long serialVersionUID = 1L;
@ApiModelProperty("导出类型companies 企业、jobs 岗位、companyJobs 企业及岗位")
private String exportType = "companies";
@ApiModelProperty("招聘会标题")
private String title;
@ApiModelProperty("举办单位")
private String hostUnit;
@ApiModelProperty("招聘会类型")
private String fairType;
@ApiModelProperty("举办区域/区域类型")
private String region;
@ApiModelProperty("场地ID")
private Long venueId;
@ApiModelProperty("场地名称")
private String venueName;
@ApiModelProperty("举办地址")
private String address;
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@ApiModelProperty("招聘会开始时间下限")
private Date startTime;
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@ApiModelProperty("招聘会结束时间上限")
private Date endTime;
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@ApiModelProperty("报名开始时间下限")
private Date applyStartTime;
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@ApiModelProperty("报名截止时间上限")
private Date applyEndTime;
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@ApiModelProperty("创建时间下限")
private Date createStartTime;
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@ApiModelProperty("创建时间上限")
private Date createEndTime;
@ApiModelProperty("举办状态NOT_STARTED 未举办ONGOING 正在举办ENDED 已举办")
private String fairStatus;
@ApiModelProperty("是否跨域Y/N仅线上招聘会使用")
private String isCrossDomain;
@ApiModelProperty("是否开启线上申请true/false仅户外招聘会使用")
private Boolean onlineApply;
@ApiModelProperty("参会企业或岗位审核状态0待审核1通过2驳回")
private String reviewStatus;
}

View File

@@ -0,0 +1,66 @@
package com.ruoyi.cms.domain.export;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
/**
* 招聘会导出行。线上和户外查询统一投影到该结构Excel 层负责字典显示值转换。
*/
@Data
public class RecruitmentFairExportRow implements Serializable
{
private static final long serialVersionUID = 1L;
private String fairId;
private String channel;
private String fairTitle;
private String fairAddress;
private String fairType;
private String fairRegion;
private String fairVenueName;
private String isCrossDomain;
private Boolean onlineApply;
private Date fairStartTime;
private Date fairEndTime;
private Date applyStartTime;
private Date applyEndTime;
private Date fairCreateTime;
private String fairHostUnit;
private String fairHelpUnit;
private String fairOrganizeUnit;
private String fairPhone;
private String fairCategory;
private Long companyId;
private String companyName;
private String companyType;
private String companyIndustry;
private String companyScale;
private String companyLocation;
private String companyCode;
private String contactPerson;
private String contactPhone;
private Integer companyStatus;
private String companyReviewStatus;
private String companyReviewRemark;
private Long jobId;
private String jobTitle;
private Integer minSalary;
private Integer maxSalary;
private String salaryComposition;
private String welfareBenefits;
private String workSchedule;
private String education;
private String experience;
private String jobType;
private String jobCategory;
private String jobLocation;
private String jobAddress;
private Integer vacancies;
private Date postingDate;
private String jobReviewStatus;
private String jobReviewRemark;
}

View File

@@ -0,0 +1,23 @@
package com.ruoyi.cms.mapper;
import com.ruoyi.cms.domain.export.RecruitmentFairExportQuery;
import com.ruoyi.cms.domain.export.RecruitmentFairExportRow;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/** 招聘会参会企业/岗位导出查询。 */
public interface RecruitmentFairExportMapper
{
List<RecruitmentFairExportRow> selectPublicCompanyRows(
@Param("query") RecruitmentFairExportQuery query);
List<RecruitmentFairExportRow> selectPublicJobRows(
@Param("query") RecruitmentFairExportQuery query);
List<RecruitmentFairExportRow> selectOutdoorCompanyRows(
@Param("query") RecruitmentFairExportQuery query);
List<RecruitmentFairExportRow> selectOutdoorJobRows(
@Param("query") RecruitmentFairExportQuery query);
}

View File

@@ -0,0 +1,402 @@
package com.ruoyi.cms.service;
import com.ruoyi.cms.domain.export.RecruitmentFairExportQuery;
import com.ruoyi.cms.domain.export.RecruitmentFairExportRow;
import com.ruoyi.cms.mapper.JobTitleMapper;
import com.ruoyi.cms.mapper.RecruitmentFairExportMapper;
import com.ruoyi.common.core.domain.entity.JobTitle;
import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.FillPatternType;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
/** 招聘会参会企业和岗位 Excel 导出服务。 */
@Service
public class RecruitmentFairExportService
{
private static final String ONLINE = "online";
private static final String OUTDOOR = "outdoor";
private static final String COMPANIES = "companies";
private static final String JOBS = "jobs";
private static final String COMPANY_JOBS = "companyJobs";
private static final String DATE_PATTERN = "yyyy-MM-dd HH:mm:ss";
private static final List<String> COMPANY_HEADERS = Arrays.asList(
"招聘会标题", "招聘会类型", "区域/举办区域", "是否跨域", "是否线上申请", "举办状态",
"开始时间", "结束时间", "报名开始时间", "报名截止时间", "创建时间", "招聘会地址", "举办单位", "协办单位",
"组织单位", "招聘会联系电话", "招聘会分类", "场地", "参会企业", "企业ID", "企业类型", "所属行业", "企业规模", "企业地址", "统一社会信用代码",
"联系人", "联系电话", "企业审核状态", "企业审核意见");
private static final List<String> JOB_HEADERS = Arrays.asList(
"招聘会标题", "招聘会类型", "区域/举办区域", "是否跨域", "是否线上申请", "举办状态",
"开始时间", "结束时间", "报名开始时间", "报名截止时间", "创建时间", "招聘会地址", "举办单位", "协办单位",
"组织单位", "招聘会联系电话", "招聘会分类", "场地", "参会企业", "企业ID", "企业类型", "所属行业", "企业规模", "联系人", "联系电话", "企业审核状态",
"企业审核意见", "岗位名称", "岗位ID", "最低薪资(元)", "最高薪资(元)", "薪资构成",
"福利待遇", "工作时间安排", "学历要求", "工作经验", "岗位类型", "岗位分类", "岗位区划",
"工作地址", "招聘人数", "发布时间", "岗位审核状态", "岗位审核意见");
@Autowired
private RecruitmentFairExportMapper exportMapper;
@Autowired
private JobTitleMapper jobTitleMapper;
/**
* 导出指定渠道的数据。导出类型由 query.exportType 决定。
*/
public void export(HttpServletResponse response, String channel, RecruitmentFairExportQuery query)
throws IOException
{
RecruitmentFairExportQuery condition = query == null ? new RecruitmentFairExportQuery() : query;
String exportType = normalizeExportType(condition.getExportType());
List<RecruitmentFairExportRow> rows = queryRows(channel, exportType, condition);
try (Workbook workbook = new XSSFWorkbook()) {
CellStyle headerStyle = createHeaderStyle(workbook);
if (COMPANIES.equals(exportType)) {
writeRows(workbook.createSheet("参会企业"), COMPANY_HEADERS, rows, headerStyle,
this::companyValues);
} else if (JOBS.equals(exportType)) {
writeRows(workbook.createSheet("参加岗位"), JOB_HEADERS, rows, headerStyle,
this::jobValues);
} else {
writeCompanySheets(workbook, rows, headerStyle);
}
response.reset();
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setCharacterEncoding(StandardCharsets.UTF_8.name());
String channelName = ONLINE.equals(channel) ? "线上招聘会" : "户外招聘会";
String fileName = channelName + "参会数据_" + System.currentTimeMillis() + ".xlsx";
String encodedFileName = URLEncoder.encode(fileName, StandardCharsets.UTF_8.name())
.replace("+", "%20");
response.setHeader("Content-Disposition", "attachment; filename*=UTF-8''" + encodedFileName);
workbook.write(response.getOutputStream());
response.flushBuffer();
}
}
private List<RecruitmentFairExportRow> queryRows(String channel, String exportType,
RecruitmentFairExportQuery query)
{
boolean online = ONLINE.equals(channel);
if (COMPANIES.equals(exportType)) {
return online ? exportMapper.selectPublicCompanyRows(query)
: exportMapper.selectOutdoorCompanyRows(query);
}
if (JOBS.equals(exportType)) {
return online ? exportMapper.selectPublicJobRows(query)
: exportMapper.selectOutdoorJobRows(query);
}
// 组合导出需要同时保留“没有岗位的参会企业”,因此分别查询企业和岗位。
List<RecruitmentFairExportRow> companies = online
? exportMapper.selectPublicCompanyRows(query)
: exportMapper.selectOutdoorCompanyRows(query);
List<RecruitmentFairExportRow> jobs = online
? exportMapper.selectPublicJobRows(query)
: exportMapper.selectOutdoorJobRows(query);
List<RecruitmentFairExportRow> result = new ArrayList<>(companies);
result.addAll(jobs);
return result;
}
private String normalizeExportType(String exportType)
{
if (JOBS.equals(exportType) || COMPANY_JOBS.equals(exportType)) {
return exportType;
}
return COMPANIES;
}
private CellStyle createHeaderStyle(Workbook workbook)
{
CellStyle style = workbook.createCellStyle();
style.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
style.setAlignment(HorizontalAlignment.CENTER);
style.setBorderBottom(BorderStyle.THIN);
style.setBorderTop(BorderStyle.THIN);
style.setBorderLeft(BorderStyle.THIN);
style.setBorderRight(BorderStyle.THIN);
Font font = workbook.createFont();
font.setBold(true);
style.setFont(font);
return style;
}
private void writeRows(Sheet sheet, List<String> headers, List<RecruitmentFairExportRow> rows,
CellStyle headerStyle, RowValues values)
{
writeHeader(sheet, headers, headerStyle);
int rowIndex = 1;
for (RecruitmentFairExportRow rowData : rows == null ? Collections.emptyList() : rows) {
Row row = sheet.createRow(rowIndex++);
List<Object> rowValues = values.values(rowData);
for (int i = 0; i < rowValues.size(); i++) {
setCellValue(row.createCell(i), rowValues.get(i));
}
}
sizeColumns(sheet, headers.size());
}
private void writeCompanySheets(Workbook workbook, List<RecruitmentFairExportRow> rows,
CellStyle headerStyle)
{
Map<String, List<RecruitmentFairExportRow>> groups = new LinkedHashMap<>();
for (RecruitmentFairExportRow row : rows == null ? Collections.emptyList() : rows) {
String key = row.getCompanyId() == null ? safe(row.getCompanyName())
: String.valueOf(row.getCompanyId());
groups.computeIfAbsent(key, ignored -> new ArrayList<>()).add(row);
}
if (groups.isEmpty()) {
writeRows(workbook.createSheet("企业岗位"), JOB_HEADERS, Collections.emptyList(), headerStyle,
this::jobValues);
return;
}
Set<String> sheetNames = new LinkedHashSet<>();
for (List<RecruitmentFairExportRow> companyRows : groups.values()) {
RecruitmentFairExportRow first = companyRows.get(0);
String baseName = "企业-" + safe(first.getCompanyName());
String sheetName = uniqueSheetName(baseName, sheetNames);
Sheet sheet = workbook.createSheet(sheetName);
writeHeader(sheet, JOB_HEADERS, headerStyle);
// 同一企业可能参加多场招聘会;只补充没有岗位的场次,避免组合导出遗漏企业。
Set<String> fairIdsWithJobs = new LinkedHashSet<>();
List<RecruitmentFairExportRow> jobRows = new ArrayList<>();
List<RecruitmentFairExportRow> companyOnlyRows = new ArrayList<>();
for (RecruitmentFairExportRow row : companyRows) {
if (row.getJobId() == null) {
companyOnlyRows.add(row);
} else {
jobRows.add(row);
fairIdsWithJobs.add(safe(row.getFairId()));
}
}
List<RecruitmentFairExportRow> output = new ArrayList<>(jobRows);
for (RecruitmentFairExportRow row : companyOnlyRows) {
if (!fairIdsWithJobs.contains(safe(row.getFairId()))) {
output.add(row);
}
}
int rowIndex = 1;
for (RecruitmentFairExportRow rowData : output) {
Row row = sheet.createRow(rowIndex++);
List<Object> rowValues = jobValues(rowData);
for (int i = 0; i < rowValues.size(); i++) {
setCellValue(row.createCell(i), rowValues.get(i));
}
}
sizeColumns(sheet, JOB_HEADERS.size());
}
}
private void writeHeader(Sheet sheet, List<String> headers, CellStyle style)
{
Row header = sheet.createRow(0);
header.setHeightInPoints(24);
for (int i = 0; i < headers.size(); i++) {
Cell cell = header.createCell(i);
cell.setCellValue(headers.get(i));
cell.setCellStyle(style);
}
sheet.createFreezePane(0, 1);
sheet.setAutoFilter(new org.apache.poi.ss.util.CellRangeAddress(0, 0, 0, headers.size() - 1));
}
private void sizeColumns(Sheet sheet, int columnCount)
{
for (int i = 0; i < columnCount; i++) {
sheet.autoSizeColumn(i);
int width = Math.min(sheet.getColumnWidth(i) + 512, 12000);
sheet.setColumnWidth(i, Math.max(width, 2400));
}
}
private List<Object> companyValues(RecruitmentFairExportRow row)
{
return Arrays.asList(
row.getFairTitle(), fairTypeLabel(row), regionLabel(row),
yesNo(row.getIsCrossDomain()), yesNo(row.getOnlineApply()), fairStatus(row),
date(row.getFairStartTime()), date(row.getFairEndTime()), date(row.getApplyStartTime()),
date(row.getApplyEndTime()), date(row.getFairCreateTime()), row.getFairAddress(), row.getFairHostUnit(),
row.getFairHelpUnit(), row.getFairOrganizeUnit(), row.getFairPhone(), row.getFairCategory(),
row.getFairVenueName(),
row.getCompanyName(), row.getCompanyId(), dict("company_nature", row.getCompanyType()),
dict("industry", row.getCompanyIndustry()), dict("scale", row.getCompanyScale()), row.getCompanyLocation(),
row.getCompanyCode(), row.getContactPerson(), row.getContactPhone(), review(row.getCompanyReviewStatus()),
row.getCompanyReviewRemark());
}
private List<Object> jobValues(RecruitmentFairExportRow row)
{
return Arrays.asList(
row.getFairTitle(), fairTypeLabel(row), regionLabel(row),
yesNo(row.getIsCrossDomain()), yesNo(row.getOnlineApply()), fairStatus(row),
date(row.getFairStartTime()), date(row.getFairEndTime()), date(row.getApplyStartTime()),
date(row.getApplyEndTime()), date(row.getFairCreateTime()), row.getFairAddress(), row.getFairHostUnit(),
row.getFairHelpUnit(), row.getFairOrganizeUnit(), row.getFairPhone(), row.getFairCategory(),
row.getFairVenueName(),
row.getCompanyName(), row.getCompanyId(), dict("company_nature", row.getCompanyType()),
dict("industry", row.getCompanyIndustry()), dict("scale", row.getCompanyScale()), row.getContactPerson(),
row.getContactPhone(), review(row.getCompanyReviewStatus()), row.getCompanyReviewRemark(), row.getJobTitle(),
row.getJobId(), row.getMinSalary(), row.getMaxSalary(), dict("salary_composition", row.getSalaryComposition()),
dict("welfare_benefits", row.getWelfareBenefits()), dict("work_schedule", row.getWorkSchedule()),
dict("education", row.getEducation()), dict("experience", row.getExperience()), dict("job_type", row.getJobType()),
jobCategoryLabel(row.getJobCategory()), dict("area", row.getJobLocation()), row.getJobAddress(),
row.getVacancies(), date(row.getPostingDate()), review(row.getJobReviewStatus()), row.getJobReviewRemark());
}
private String regionLabel(RecruitmentFairExportRow row)
{
String dictType = "outdoor".equals(row.getChannel()) ? "outdoor_fair_region" : "job_fair_region_type";
return dict(dictType, row.getFairRegion());
}
private String fairTypeLabel(RecruitmentFairExportRow row)
{
String dictType = "outdoor".equals(row.getChannel()) ? "outdoor_fair_type" : "job_fair_type";
return dict(dictType, row.getFairType());
}
private String dict(String type, String value)
{
if (value == null || value.trim().isEmpty()) {
return "";
}
// 招聘会类型/区域使用系统字典,企业和岗位字段使用业务字典;两套字典在项目中并存。
String label = com.ruoyi.cms.util.DictUtils.getDictLabel(type, value);
if (label == null || label.trim().isEmpty()) {
label = com.ruoyi.common.utils.DictUtils.getDictLabel(type, value);
}
return label == null || label.trim().isEmpty() ? value : label;
}
private String jobCategoryLabel(String value)
{
if (value == null || value.trim().isEmpty()) {
return "";
}
try {
JobTitle jobTitle = jobTitleMapper.selectById(Long.valueOf(value));
if (jobTitle != null && jobTitle.getJobName() != null && !jobTitle.getJobName().trim().isEmpty()) {
return jobTitle.getJobName();
}
} catch (NumberFormatException ignored) {
// 岗位分类也可能已经保存为文字,直接保留原值。
}
return value;
}
private String yesNo(Object value)
{
if (value == null) {
return "";
}
String raw = String.valueOf(value);
if ("Y".equalsIgnoreCase(raw) || "true".equalsIgnoreCase(raw) || "1".equals(raw)) {
return "";
}
if ("N".equalsIgnoreCase(raw) || "false".equalsIgnoreCase(raw) || "0".equals(raw)) {
return "";
}
return raw;
}
private String review(String value)
{
if (value == null || value.trim().isEmpty()) {
return "";
}
switch (value) {
case "0":
return "待审核";
case "1":
return "审核通过";
case "2":
return "审核不通过";
default:
return value;
}
}
private String fairStatus(RecruitmentFairExportRow row)
{
Date now = new Date();
if (row.getFairStartTime() != null && now.before(row.getFairStartTime())) {
return "未举办";
}
if (row.getFairEndTime() != null && !now.after(row.getFairEndTime())) {
return "正在举办";
}
return "已举办";
}
private String date(Date value)
{
return value == null ? "" : new SimpleDateFormat(DATE_PATTERN).format(value);
}
private String safe(String value)
{
return value == null || value.trim().isEmpty() ? "未命名企业" : value.trim();
}
private String uniqueSheetName(String value, Set<String> used)
{
String base = value.replaceAll("[\\\\/:*?\\[\\]]", "_");
if (base.length() > 31) {
base = base.substring(0, 31);
}
String candidate = base;
int suffix = 2;
while (!used.add(candidate)) {
String tail = "-" + suffix++;
int maxBaseLength = 31 - tail.length();
candidate = base.substring(0, Math.min(base.length(), maxBaseLength)) + tail;
}
return candidate;
}
private interface RowValues
{
List<Object> values(RecruitmentFairExportRow row);
}
private void setCellValue(Cell cell, Object value)
{
if (value == null) {
cell.setCellValue("");
} else if (value instanceof Number) {
cell.setCellValue(((Number) value).doubleValue());
} else {
cell.setCellValue(String.valueOf(value));
}
}
}

View File

@@ -0,0 +1,278 @@
<?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.RecruitmentFairExportMapper">
<sql id="publicFairWhere">
pf.del_flag = '0'
<if test="query.title != null and query.title != ''">
AND pf.job_fair_title LIKE CONCAT('%', CAST(#{query.title, jdbcType=VARCHAR} AS VARCHAR), '%')
</if>
<if test="query.hostUnit != null and query.hostUnit != ''">
AND pf.job_fair_host_unit LIKE CONCAT('%', CAST(#{query.hostUnit, jdbcType=VARCHAR} AS VARCHAR), '%')
</if>
<if test="query.fairType != null and query.fairType != ''">
AND pf.job_fair_type = #{query.fairType}
</if>
<if test="query.region != null and query.region != ''">
AND pf.job_fair_region_type = #{query.region}
</if>
<if test="query.address != null and query.address != ''">
AND pf.job_fair_address LIKE CONCAT('%', CAST(#{query.address, jdbcType=VARCHAR} AS VARCHAR), '%')
</if>
<if test="query.startTime != null">
AND pf.job_fair_start_time &gt;= #{query.startTime}
</if>
<if test="query.endTime != null">
AND pf.job_fair_end_time &lt;= #{query.endTime}
</if>
<if test="query.applyStartTime != null">
AND pf.job_fair_sign_up_start_time &gt;= #{query.applyStartTime}
</if>
<if test="query.applyEndTime != null">
AND pf.job_fair_sign_up_end_time &lt;= #{query.applyEndTime}
</if>
<if test="query.createStartTime != null">
AND pf.create_time &gt;= #{query.createStartTime}
</if>
<if test="query.createEndTime != null">
AND pf.create_time &lt;= #{query.createEndTime}
</if>
<if test="query.isCrossDomain != null and query.isCrossDomain != ''">
AND UPPER(COALESCE(pf.is_cross_domain, 'N')) = UPPER(#{query.isCrossDomain})
</if>
<if test="query.fairStatus == 'NOT_STARTED'">
AND pf.job_fair_start_time &gt; CURRENT_TIMESTAMP
</if>
<if test="query.fairStatus == 'ONGOING'">
AND pf.job_fair_start_time &lt;= CURRENT_TIMESTAMP
AND pf.job_fair_end_time &gt;= CURRENT_TIMESTAMP
</if>
<if test="query.fairStatus == 'ENDED'">
AND pf.job_fair_end_time &lt; CURRENT_TIMESTAMP
</if>
</sql>
<sql id="outdoorFairWhere">
pf.del_flag = '0'
<if test="query.title != null and query.title != ''">
AND pf.title LIKE CONCAT('%', CAST(#{query.title, jdbcType=VARCHAR} AS VARCHAR), '%')
</if>
<if test="query.hostUnit != null and query.hostUnit != ''">
AND pf.host_unit LIKE CONCAT('%', CAST(#{query.hostUnit, jdbcType=VARCHAR} AS VARCHAR), '%')
</if>
<if test="query.fairType != null and query.fairType != ''">
AND pf.fair_type = #{query.fairType}
</if>
<if test="query.region != null and query.region != ''">
AND pf.region = #{query.region}
</if>
<if test="query.venueId != null">
AND pf.venue_id = #{query.venueId}
</if>
<if test="query.venueName != null and query.venueName != ''">
AND pf.venue_name LIKE CONCAT('%', CAST(#{query.venueName, jdbcType=VARCHAR} AS VARCHAR), '%')
</if>
<if test="query.address != null and query.address != ''">
AND pf.address LIKE CONCAT('%', CAST(#{query.address, jdbcType=VARCHAR} AS VARCHAR), '%')
</if>
<if test="query.onlineApply != null">
AND pf.online_apply = #{query.onlineApply}
</if>
<if test="query.startTime != null">
AND pf.hold_time &gt;= #{query.startTime}
</if>
<if test="query.endTime != null">
AND pf.end_time &lt;= #{query.endTime}
</if>
<if test="query.applyStartTime != null">
AND pf.apply_start_time &gt;= #{query.applyStartTime}
</if>
<if test="query.applyEndTime != null">
AND pf.apply_end_time &lt;= #{query.applyEndTime}
</if>
<if test="query.createStartTime != null">
AND pf.create_time &gt;= #{query.createStartTime}
</if>
<if test="query.createEndTime != null">
AND pf.create_time &lt;= #{query.createEndTime}
</if>
<if test="query.fairStatus == 'NOT_STARTED'">
AND pf.hold_time &gt; CURRENT_TIMESTAMP
</if>
<if test="query.fairStatus == 'ONGOING'">
AND pf.hold_time &lt;= CURRENT_TIMESTAMP
AND pf.end_time &gt;= CURRENT_TIMESTAMP
</if>
<if test="query.fairStatus == 'ENDED'">
AND pf.end_time &lt; CURRENT_TIMESTAMP
</if>
</sql>
<sql id="publicFairColumns">
'online' AS channel,
pf.job_fair_id AS fair_id,
pf.job_fair_title AS fair_title,
pf.job_fair_address AS fair_address,
pf.job_fair_type AS fair_type,
pf.job_fair_region_type AS fair_region,
NULL AS fair_venue_name,
pf.is_cross_domain,
NULL AS online_apply,
pf.job_fair_start_time AS fair_start_time,
pf.job_fair_end_time AS fair_end_time,
pf.job_fair_sign_up_start_time AS apply_start_time,
pf.job_fair_sign_up_end_time AS apply_end_time,
pf.create_time AS fair_create_time,
pf.job_fair_host_unit AS fair_host_unit,
pf.job_fair_help_unit AS fair_help_unit,
pf.job_fair_organize_unit AS fair_organize_unit,
pf.job_fair_phone AS fair_phone,
pf.job_fair_category AS fair_category
</sql>
<sql id="outdoorFairColumns">
'outdoor' AS channel,
CAST(pf.id AS VARCHAR) AS fair_id,
pf.title AS fair_title,
pf.address AS fair_address,
pf.fair_type,
pf.region AS fair_region,
pf.venue_name AS fair_venue_name,
NULL AS is_cross_domain,
pf.online_apply,
pf.hold_time AS fair_start_time,
pf.end_time AS fair_end_time,
pf.apply_start_time,
pf.apply_end_time,
pf.create_time AS fair_create_time,
pf.host_unit AS fair_host_unit,
NULL AS fair_help_unit,
NULL AS fair_organize_unit,
NULL AS fair_phone,
NULL AS fair_category
</sql>
<sql id="companyColumns">
c.company_id,
c.name AS company_name,
COALESCE(c.company_nature, c.nature) AS company_type,
c.industry AS company_industry,
c.scale AS company_scale,
c.location AS company_location,
c.code AS company_code,
c.contact_person,
c.contact_person_phone AS contact_phone,
c.status AS company_status
</sql>
<sql id="jobColumns">
j.job_id,
j.job_title,
j.min_salary,
j.max_salary,
j.salary_composition,
j.welfare_benefits,
j.work_schedule,
j.education,
j.experience,
j.job_type,
j.job_category,
j.job_location,
j.job_address,
j.vacancies,
j.posting_date,
j.description
</sql>
<select id="selectPublicCompanyRows" resultType="com.ruoyi.cms.domain.export.RecruitmentFairExportRow">
SELECT
<include refid="publicFairColumns"/>,
<include refid="companyColumns"/>,
pfc.review_status AS company_review_status,
pfc.review_remark AS company_review_remark
FROM public_job_fair_company pfc
INNER JOIN public_job_fair pf ON pf.job_fair_id = pfc.job_fair_id
LEFT JOIN company c ON c.company_id = pfc.company_id
<where>
<include refid="publicFairWhere"/>
AND pfc.del_flag = '0'
<if test="query.reviewStatus != null and query.reviewStatus != ''">
AND COALESCE(pfc.review_status, '1') = #{query.reviewStatus}
</if>
</where>
ORDER BY pf.job_fair_start_time DESC NULLS LAST, c.name ASC NULLS LAST
</select>
<select id="selectPublicJobRows" resultType="com.ruoyi.cms.domain.export.RecruitmentFairExportRow">
SELECT
<include refid="publicFairColumns"/>,
<include refid="companyColumns"/>,
pfc.review_status AS company_review_status,
pfc.review_remark AS company_review_remark,
j.review_status AS job_review_status,
NULL AS job_review_remark,
<include refid="jobColumns"/>
FROM public_job_fair_job pfj
INNER JOIN public_job_fair pf ON pf.job_fair_id = pfj.job_fair_id
INNER JOIN public_job_fair_company pfc
ON pfc.job_fair_id = pfj.job_fair_id
AND pfc.company_id = pfj.company_id
AND pfc.del_flag = '0'
INNER JOIN job j ON j.job_id = pfj.job_id AND j.del_flag = '0'
LEFT JOIN company c ON c.company_id = pfj.company_id
<where>
<include refid="publicFairWhere"/>
AND pfj.del_flag = '0'
<if test="query.reviewStatus != null and query.reviewStatus != ''">
AND COALESCE(pfc.review_status, '1') = #{query.reviewStatus}
</if>
</where>
ORDER BY pf.job_fair_start_time DESC NULLS LAST, c.name ASC NULLS LAST, j.job_title ASC NULLS LAST
</select>
<select id="selectOutdoorCompanyRows" resultType="com.ruoyi.cms.domain.export.RecruitmentFairExportRow">
SELECT
<include refid="outdoorFairColumns"/>,
<include refid="companyColumns"/>,
COALESCE(fc.review_status, '1') AS company_review_status,
fc.review_remark AS company_review_remark
FROM fair_company fc
INNER JOIN cms_outdoor_fair pf ON pf.id = fc.job_fair_id
LEFT JOIN company c ON c.company_id = fc.company_id
<where>
<include refid="outdoorFairWhere"/>
AND COALESCE(fc.del_flag, '0') = '0'
<if test="query.reviewStatus != null and query.reviewStatus != ''">
AND COALESCE(fc.review_status, '1') = #{query.reviewStatus}
</if>
</where>
ORDER BY pf.hold_time DESC NULLS LAST, c.name ASC NULLS LAST
</select>
<select id="selectOutdoorJobRows" resultType="com.ruoyi.cms.domain.export.RecruitmentFairExportRow">
SELECT
<include refid="outdoorFairColumns"/>,
<include refid="companyColumns"/>,
COALESCE(fc.review_status, '1') AS company_review_status,
fc.review_remark AS company_review_remark,
COALESCE(pfj.review_status, '1') AS job_review_status,
pfj.review_remark AS job_review_remark,
<include refid="jobColumns"/>
FROM cms_outdoor_fair_job pfj
INNER JOIN cms_outdoor_fair pf ON pf.id = pfj.fair_id
LEFT JOIN fair_company fc
ON fc.job_fair_id = pfj.fair_id
AND fc.company_id = pfj.company_id
AND COALESCE(fc.del_flag, '0') = '0'
INNER JOIN job j ON j.job_id = pfj.job_id AND j.del_flag = '0'
LEFT JOIN company c ON c.company_id = pfj.company_id
<where>
<include refid="outdoorFairWhere"/>
AND COALESCE(pfj.del_flag, '0') = '0'
<if test="query.reviewStatus != null and query.reviewStatus != ''">
AND COALESCE(pfj.review_status, fc.review_status, '1') = #{query.reviewStatus}
</if>
</where>
ORDER BY pf.hold_time DESC NULLS LAST, c.name ASC NULLS LAST, j.job_title ASC NULLS LAST
</select>
</mapper>