docs: 添加员工信息导入结果弹窗自适应优化设计文档
- 分析现有问题:弹窗内容过多时超出视口 - 设计固定高度+内容可滚动的Flexbox布局方案 - 提供完整的CSS样式和响应式设计 - 包含实施计划、验收标准和技术要点 Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,134 @@
|
||||
package com.ruoyi.ccdi.controller;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.ruoyi.ccdi.domain.dto.CcdiStaffRecruitmentAddDTO;
|
||||
import com.ruoyi.ccdi.domain.dto.CcdiStaffRecruitmentEditDTO;
|
||||
import com.ruoyi.ccdi.domain.dto.CcdiStaffRecruitmentQueryDTO;
|
||||
import com.ruoyi.ccdi.domain.excel.CcdiStaffRecruitmentExcel;
|
||||
import com.ruoyi.ccdi.domain.vo.CcdiStaffRecruitmentVO;
|
||||
import com.ruoyi.ccdi.service.ICcdiStaffRecruitmentService;
|
||||
import com.ruoyi.ccdi.utils.EasyExcelUtil;
|
||||
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.PageDomain;
|
||||
import com.ruoyi.common.core.page.TableDataInfo;
|
||||
import com.ruoyi.common.core.page.TableSupport;
|
||||
import com.ruoyi.common.enums.BusinessType;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 员工招聘信息Controller
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-02-05
|
||||
*/
|
||||
@Tag(name = "员工招聘信息管理")
|
||||
@RestController
|
||||
@RequestMapping("/ccdi/staffRecruitment")
|
||||
public class CcdiStaffRecruitmentController extends BaseController {
|
||||
|
||||
@Resource
|
||||
private ICcdiStaffRecruitmentService recruitmentService;
|
||||
|
||||
/**
|
||||
* 查询招聘信息列表
|
||||
*/
|
||||
@Operation(summary = "查询招聘信息列表")
|
||||
@PreAuthorize("@ss.hasPermi('ccdi:staffRecruitment:list')")
|
||||
@GetMapping("/list")
|
||||
public TableDataInfo list(CcdiStaffRecruitmentQueryDTO queryDTO) {
|
||||
// 使用MyBatis Plus分页
|
||||
PageDomain pageDomain = TableSupport.buildPageRequest();
|
||||
Page<CcdiStaffRecruitmentVO> page = new Page<>(pageDomain.getPageNum(), pageDomain.getPageSize());
|
||||
Page<CcdiStaffRecruitmentVO> result = recruitmentService.selectRecruitmentPage(page, queryDTO);
|
||||
return getDataTable(result.getRecords(), result.getTotal());
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出招聘信息列表
|
||||
*/
|
||||
@Operation(summary = "导出招聘信息列表")
|
||||
@PreAuthorize("@ss.hasPermi('ccdi:staffRecruitment:export')")
|
||||
@Log(title = "员工招聘信息", businessType = BusinessType.EXPORT)
|
||||
@PostMapping("/export")
|
||||
public void export(HttpServletResponse response, CcdiStaffRecruitmentQueryDTO queryDTO) {
|
||||
List<CcdiStaffRecruitmentExcel> list = recruitmentService.selectRecruitmentListForExport(queryDTO);
|
||||
EasyExcelUtil.exportExcel(response, list, CcdiStaffRecruitmentExcel.class, "员工招聘信息");
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取招聘信息详细信息
|
||||
*/
|
||||
@Operation(summary = "获取招聘信息详细信息")
|
||||
@PreAuthorize("@ss.hasPermi('ccdi:staffRecruitment:query')")
|
||||
@GetMapping(value = "/{recruitId}")
|
||||
public AjaxResult getInfo(@PathVariable String recruitId) {
|
||||
return success(recruitmentService.selectRecruitmentById(recruitId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增招聘信息
|
||||
*/
|
||||
@Operation(summary = "新增招聘信息")
|
||||
@PreAuthorize("@ss.hasPermi('ccdi:staffRecruitment:add')")
|
||||
@Log(title = "员工招聘信息", businessType = BusinessType.INSERT)
|
||||
@PostMapping
|
||||
public AjaxResult add(@Validated @RequestBody CcdiStaffRecruitmentAddDTO addDTO) {
|
||||
return toAjax(recruitmentService.insertRecruitment(addDTO));
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改招聘信息
|
||||
*/
|
||||
@Operation(summary = "修改招聘信息")
|
||||
@PreAuthorize("@ss.hasPermi('ccdi:staffRecruitment:edit')")
|
||||
@Log(title = "员工招聘信息", businessType = BusinessType.UPDATE)
|
||||
@PutMapping
|
||||
public AjaxResult edit(@Validated @RequestBody CcdiStaffRecruitmentEditDTO editDTO) {
|
||||
return toAjax(recruitmentService.updateRecruitment(editDTO));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除招聘信息
|
||||
*/
|
||||
@Operation(summary = "删除招聘信息")
|
||||
@PreAuthorize("@ss.hasPermi('ccdi:staffRecruitment:remove')")
|
||||
@Log(title = "员工招聘信息", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{recruitIds}")
|
||||
public AjaxResult remove(@PathVariable String[] recruitIds) {
|
||||
return toAjax(recruitmentService.deleteRecruitmentByIds(recruitIds));
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载带字典下拉框的导入模板
|
||||
* 使用@DictDropdown注解自动添加下拉框
|
||||
*/
|
||||
@Operation(summary = "下载导入模板")
|
||||
@PostMapping("/importTemplate")
|
||||
public void importTemplate(HttpServletResponse response) {
|
||||
EasyExcelUtil.importTemplateWithDictDropdown(response, CcdiStaffRecruitmentExcel.class, "员工招聘信息");
|
||||
}
|
||||
|
||||
/**
|
||||
* 导入招聘信息
|
||||
*/
|
||||
@Operation(summary = "导入招聘信息")
|
||||
@PreAuthorize("@ss.hasPermi('ccdi:staffRecruitment:import')")
|
||||
@Log(title = "员工招聘信息", businessType = BusinessType.IMPORT)
|
||||
@PostMapping("/importData")
|
||||
public AjaxResult importData(MultipartFile file, boolean updateSupport) throws Exception {
|
||||
List<CcdiStaffRecruitmentExcel> list = EasyExcelUtil.importExcel(file.getInputStream(), CcdiStaffRecruitmentExcel.class);
|
||||
String message = recruitmentService.importRecruitment(list, updateSupport);
|
||||
return success(message);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
package com.ruoyi.ccdi.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.FieldFill;
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 员工招聘信息对象 ccdi_staff_recruitment
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-02-05
|
||||
*/
|
||||
@Data
|
||||
public class CcdiStaffRecruitment implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** 招聘项目编号 */
|
||||
@TableId(type = IdType.INPUT)
|
||||
private String recruitId;
|
||||
|
||||
/** 招聘项目名称 */
|
||||
private String recruitName;
|
||||
|
||||
/** 职位名称 */
|
||||
private String posName;
|
||||
|
||||
/** 职位类别 */
|
||||
private String posCategory;
|
||||
|
||||
/** 职位描述 */
|
||||
private String posDesc;
|
||||
|
||||
/** 应聘人员姓名 */
|
||||
private String candName;
|
||||
|
||||
/** 应聘人员学历 */
|
||||
private String candEdu;
|
||||
|
||||
/** 应聘人员证件号码 */
|
||||
private String candId;
|
||||
|
||||
/** 应聘人员毕业院校 */
|
||||
private String candSchool;
|
||||
|
||||
/** 应聘人员专业 */
|
||||
private String candMajor;
|
||||
|
||||
/** 应聘人员毕业年月 */
|
||||
private String candGrad;
|
||||
|
||||
/** 录用情况:录用、未录用、放弃 */
|
||||
private String admitStatus;
|
||||
|
||||
/** 面试官1姓名 */
|
||||
private String interviewerName1;
|
||||
|
||||
/** 面试官1工号 */
|
||||
private String interviewerId1;
|
||||
|
||||
/** 面试官2姓名 */
|
||||
private String interviewerName2;
|
||||
|
||||
/** 面试官2工号 */
|
||||
private String interviewerId2;
|
||||
|
||||
/** 记录创建人 */
|
||||
@TableField(fill = FieldFill.INSERT)
|
||||
private String createdBy;
|
||||
|
||||
/** 记录更新人 */
|
||||
@TableField(fill = FieldFill.INSERT_UPDATE)
|
||||
private String updatedBy;
|
||||
|
||||
/** 创建时间 */
|
||||
@TableField(fill = FieldFill.INSERT)
|
||||
private Date createTime;
|
||||
|
||||
/** 更新时间 */
|
||||
@TableField(fill = FieldFill.INSERT_UPDATE)
|
||||
private Date updateTime;
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
package com.ruoyi.ccdi.domain.dto;
|
||||
|
||||
import com.ruoyi.ccdi.annotation.EnumValid;
|
||||
import com.ruoyi.ccdi.enums.AdmitStatus;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.Pattern;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 员工招聘信息新增DTO
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-02-05
|
||||
*/
|
||||
@Data
|
||||
public class CcdiStaffRecruitmentAddDTO implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** 招聘项目编号 */
|
||||
@NotBlank(message = "招聘项目编号不能为空")
|
||||
@Size(max = 32, message = "招聘项目编号长度不能超过32个字符")
|
||||
private String recruitId;
|
||||
|
||||
/** 招聘项目名称 */
|
||||
@NotBlank(message = "招聘项目名称不能为空")
|
||||
@Size(max = 100, message = "招聘项目名称长度不能超过100个字符")
|
||||
private String recruitName;
|
||||
|
||||
/** 职位名称 */
|
||||
@NotBlank(message = "职位名称不能为空")
|
||||
@Size(max = 100, message = "职位名称长度不能超过100个字符")
|
||||
private String posName;
|
||||
|
||||
/** 职位类别 */
|
||||
@NotBlank(message = "职位类别不能为空")
|
||||
@Size(max = 50, message = "职位类别长度不能超过50个字符")
|
||||
private String posCategory;
|
||||
|
||||
/** 职位描述 */
|
||||
@NotBlank(message = "职位描述不能为空")
|
||||
private String posDesc;
|
||||
|
||||
/** 应聘人员姓名 */
|
||||
@NotBlank(message = "应聘人员姓名不能为空")
|
||||
@Size(max = 20, message = "应聘人员姓名长度不能超过20个字符")
|
||||
private String candName;
|
||||
|
||||
/** 应聘人员学历 */
|
||||
@NotBlank(message = "应聘人员学历不能为空")
|
||||
@Size(max = 20, message = "应聘人员学历长度不能超过20个字符")
|
||||
private String candEdu;
|
||||
|
||||
/** 应聘人员证件号码 */
|
||||
@NotBlank(message = "证件号码不能为空")
|
||||
@Pattern(regexp = "^[1-9]\\d{5}(18|19|20)\\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\\d|3[01])\\d{3}[0-9Xx]$", message = "证件号码格式不正确")
|
||||
private String candId;
|
||||
|
||||
/** 应聘人员毕业院校 */
|
||||
@NotBlank(message = "应聘人员毕业院校不能为空")
|
||||
@Size(max = 50, message = "应聘人员毕业院校长度不能超过50个字符")
|
||||
private String candSchool;
|
||||
|
||||
/** 应聘人员专业 */
|
||||
@NotBlank(message = "应聘人员专业不能为空")
|
||||
@Size(max = 30, message = "应聘人员专业长度不能超过30个字符")
|
||||
private String candMajor;
|
||||
|
||||
/** 应聘人员毕业年月 */
|
||||
@NotBlank(message = "应聘人员毕业年月不能为空")
|
||||
@Pattern(regexp = "^((19|20)\\d{2})(0[1-9]|1[0-2])$", message = "毕业年月格式不正确,应为YYYYMM")
|
||||
private String candGrad;
|
||||
|
||||
/** 录用情况:录用、未录用、放弃 */
|
||||
@NotBlank(message = "录用情况不能为空")
|
||||
@EnumValid(enumClass = AdmitStatus.class, message = "录用情况状态值不合法")
|
||||
private String admitStatus;
|
||||
|
||||
/** 面试官1姓名 */
|
||||
@Size(max = 20, message = "面试官1姓名长度不能超过20个字符")
|
||||
private String interviewerName1;
|
||||
|
||||
/** 面试官1工号 */
|
||||
@Size(max = 10, message = "面试官1工号长度不能超过10个字符")
|
||||
private String interviewerId1;
|
||||
|
||||
/** 面试官2姓名 */
|
||||
@Size(max = 20, message = "面试官2姓名长度不能超过20个字符")
|
||||
private String interviewerName2;
|
||||
|
||||
/** 面试官2工号 */
|
||||
@Size(max = 10, message = "面试官2工号长度不能超过10个字符")
|
||||
private String interviewerId2;
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
package com.ruoyi.ccdi.domain.dto;
|
||||
|
||||
import com.ruoyi.ccdi.annotation.EnumValid;
|
||||
import com.ruoyi.ccdi.enums.AdmitStatus;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Pattern;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 员工招聘信息编辑DTO
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-02-05
|
||||
*/
|
||||
@Data
|
||||
public class CcdiStaffRecruitmentEditDTO implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** 招聘项目编号 */
|
||||
@NotNull(message = "招聘项目编号不能为空")
|
||||
private String recruitId;
|
||||
|
||||
/** 招聘项目名称 */
|
||||
@Size(max = 100, message = "招聘项目名称长度不能超过100个字符")
|
||||
private String recruitName;
|
||||
|
||||
/** 职位名称 */
|
||||
@Size(max = 100, message = "职位名称长度不能超过100个字符")
|
||||
private String posName;
|
||||
|
||||
/** 职位类别 */
|
||||
@Size(max = 50, message = "职位类别长度不能超过50个字符")
|
||||
private String posCategory;
|
||||
|
||||
/** 职位描述 */
|
||||
private String posDesc;
|
||||
|
||||
/** 应聘人员姓名 */
|
||||
@Size(max = 20, message = "应聘人员姓名长度不能超过20个字符")
|
||||
private String candName;
|
||||
|
||||
/** 应聘人员学历 */
|
||||
@Size(max = 20, message = "应聘人员学历长度不能超过20个字符")
|
||||
private String candEdu;
|
||||
|
||||
/** 应聘人员证件号码 */
|
||||
@NotBlank(message = "证件号码不能为空")
|
||||
@Pattern(regexp = "^[1-9]\\d{5}(18|19|20)\\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\\d|3[01])\\d{3}[0-9Xx]$", message = "证件号码格式不正确")
|
||||
private String candId;
|
||||
|
||||
/** 应聘人员毕业院校 */
|
||||
@Size(max = 50, message = "应聘人员毕业院校长度不能超过50个字符")
|
||||
private String candSchool;
|
||||
|
||||
/** 应聘人员专业 */
|
||||
@Size(max = 30, message = "应聘人员专业长度不能超过30个字符")
|
||||
private String candMajor;
|
||||
|
||||
/** 应聘人员毕业年月 */
|
||||
@Pattern(regexp = "^((19|20)\\d{2})(0[1-9]|1[0-2])$", message = "毕业年月格式不正确,应为YYYYMM")
|
||||
private String candGrad;
|
||||
|
||||
/** 录用情况:录用、未录用、放弃 */
|
||||
@EnumValid(enumClass = AdmitStatus.class, message = "录用情况状态值不合法")
|
||||
private String admitStatus;
|
||||
|
||||
/** 面试官1姓名 */
|
||||
@Size(max = 20, message = "面试官1姓名长度不能超过20个字符")
|
||||
private String interviewerName1;
|
||||
|
||||
/** 面试官1工号 */
|
||||
@Size(max = 10, message = "面试官1工号长度不能超过10个字符")
|
||||
private String interviewerId1;
|
||||
|
||||
/** 面试官2姓名 */
|
||||
@Size(max = 20, message = "面试官2姓名长度不能超过20个字符")
|
||||
private String interviewerName2;
|
||||
|
||||
/** 面试官2工号 */
|
||||
@Size(max = 10, message = "面试官2工号长度不能超过10个字符")
|
||||
private String interviewerId2;
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package com.ruoyi.ccdi.domain.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 员工招聘信息查询DTO
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-02-05
|
||||
*/
|
||||
@Data
|
||||
public class CcdiStaffRecruitmentQueryDTO implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** 招聘项目名称(模糊查询) */
|
||||
private String recruitName;
|
||||
|
||||
/** 职位名称(模糊查询) */
|
||||
private String posName;
|
||||
|
||||
/** 候选人姓名(模糊查询) */
|
||||
private String candName;
|
||||
|
||||
/** 证件号码(精确查询) */
|
||||
private String candId;
|
||||
|
||||
/** 录用状态(精确查询) */
|
||||
private String admitStatus;
|
||||
|
||||
/** 面试官姓名(模糊查询,查询面试官1或2) */
|
||||
private String interviewerName;
|
||||
|
||||
/** 面试官工号(精确查询,查询面试官1或2) */
|
||||
private String interviewerId;
|
||||
|
||||
/** 分页参数 */
|
||||
private Integer pageNum = 1;
|
||||
|
||||
/** 分页参数 */
|
||||
private Integer pageSize = 10;
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
package com.ruoyi.ccdi.domain.excel;
|
||||
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
import com.alibaba.excel.annotation.write.style.ColumnWidth;
|
||||
import com.ruoyi.common.annotation.DictDropdown;
|
||||
import com.ruoyi.common.annotation.Required;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 员工招聘信息Excel导入导出对象
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-02-05
|
||||
*/
|
||||
@Data
|
||||
public class CcdiStaffRecruitmentExcel implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** 招聘项目编号 */
|
||||
@ExcelProperty(value = "招聘项目编号", index = 0)
|
||||
@ColumnWidth(20)
|
||||
@Required
|
||||
private String recruitId;
|
||||
|
||||
/** 招聘项目名称 */
|
||||
@ExcelProperty(value = "招聘项目名称", index = 1)
|
||||
@ColumnWidth(20)
|
||||
@Required
|
||||
private String recruitName;
|
||||
|
||||
/** 职位名称 */
|
||||
@ExcelProperty(value = "职位名称", index = 2)
|
||||
@ColumnWidth(20)
|
||||
@Required
|
||||
private String posName;
|
||||
|
||||
/** 职位类别 */
|
||||
@ExcelProperty(value = "职位类别", index = 3)
|
||||
@ColumnWidth(15)
|
||||
@Required
|
||||
private String posCategory;
|
||||
|
||||
/** 职位描述 */
|
||||
@ExcelProperty(value = "职位描述", index = 4)
|
||||
@ColumnWidth(30)
|
||||
@Required
|
||||
private String posDesc;
|
||||
|
||||
/** 应聘人员姓名 */
|
||||
@ExcelProperty(value = "应聘人员姓名", index = 5)
|
||||
@ColumnWidth(15)
|
||||
@Required
|
||||
private String candName;
|
||||
|
||||
/** 应聘人员学历 */
|
||||
@ExcelProperty(value = "应聘人员学历", index = 6)
|
||||
@ColumnWidth(15)
|
||||
@Required
|
||||
private String candEdu;
|
||||
|
||||
/** 应聘人员证件号码 */
|
||||
@ExcelProperty(value = "应聘人员证件号码", index = 7)
|
||||
@ColumnWidth(20)
|
||||
@Required
|
||||
private String candId;
|
||||
|
||||
/** 应聘人员毕业院校 */
|
||||
@ExcelProperty(value = "应聘人员毕业院校", index = 8)
|
||||
@ColumnWidth(20)
|
||||
@Required
|
||||
private String candSchool;
|
||||
|
||||
/** 应聘人员专业 */
|
||||
@ExcelProperty(value = "应聘人员专业", index = 9)
|
||||
@ColumnWidth(15)
|
||||
@Required
|
||||
private String candMajor;
|
||||
|
||||
/** 应聘人员毕业年月 */
|
||||
@ExcelProperty(value = "应聘人员毕业年月", index = 10)
|
||||
@ColumnWidth(15)
|
||||
@Required
|
||||
private String candGrad;
|
||||
|
||||
/** 录用情况 */
|
||||
@ExcelProperty(value = "录用情况", index = 11)
|
||||
@ColumnWidth(10)
|
||||
@DictDropdown(dictType = "ccdi_admit_status")
|
||||
@Required
|
||||
private String admitStatus;
|
||||
|
||||
/** 面试官1姓名 */
|
||||
@ExcelProperty(value = "面试官1姓名", index = 12)
|
||||
@ColumnWidth(15)
|
||||
private String interviewerName1;
|
||||
|
||||
/** 面试官1工号 */
|
||||
@ExcelProperty(value = "面试官1工号", index = 13)
|
||||
@ColumnWidth(15)
|
||||
private String interviewerId1;
|
||||
|
||||
/** 面试官2姓名 */
|
||||
@ExcelProperty(value = "面试官2姓名", index = 14)
|
||||
@ColumnWidth(15)
|
||||
private String interviewerName2;
|
||||
|
||||
/** 面试官2工号 */
|
||||
@ExcelProperty(value = "面试官2工号", index = 15)
|
||||
@ColumnWidth(15)
|
||||
private String interviewerId2;
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
package com.ruoyi.ccdi.domain.vo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 员工招聘信息VO
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-02-05
|
||||
*/
|
||||
@Data
|
||||
public class CcdiStaffRecruitmentVO implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** 招聘项目编号 */
|
||||
private String recruitId;
|
||||
|
||||
/** 招聘项目名称 */
|
||||
private String recruitName;
|
||||
|
||||
/** 职位名称 */
|
||||
private String posName;
|
||||
|
||||
/** 职位类别 */
|
||||
private String posCategory;
|
||||
|
||||
/** 职位描述 */
|
||||
private String posDesc;
|
||||
|
||||
/** 应聘人员姓名 */
|
||||
private String candName;
|
||||
|
||||
/** 应聘人员学历 */
|
||||
private String candEdu;
|
||||
|
||||
/** 应聘人员证件号码 */
|
||||
private String candId;
|
||||
|
||||
/** 应聘人员毕业院校 */
|
||||
private String candSchool;
|
||||
|
||||
/** 应聘人员专业 */
|
||||
private String candMajor;
|
||||
|
||||
/** 应聘人员毕业年月 */
|
||||
private String candGrad;
|
||||
|
||||
/** 录用情况:录用、未录用、放弃 */
|
||||
private String admitStatus;
|
||||
|
||||
/** 录用情况描述 */
|
||||
private String admitStatusDesc;
|
||||
|
||||
/** 面试官1姓名 */
|
||||
private String interviewerName1;
|
||||
|
||||
/** 面试官1工号 */
|
||||
private String interviewerId1;
|
||||
|
||||
/** 面试官2姓名 */
|
||||
private String interviewerName2;
|
||||
|
||||
/** 面试官2工号 */
|
||||
private String interviewerId2;
|
||||
|
||||
/** 记录创建人 */
|
||||
private String createdBy;
|
||||
|
||||
/** 创建时间 */
|
||||
private Date createTime;
|
||||
|
||||
/** 记录更新人 */
|
||||
private String updatedBy;
|
||||
|
||||
/** 更新时间 */
|
||||
private Date updateTime;
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package com.ruoyi.ccdi.enums;
|
||||
|
||||
|
||||
/**
|
||||
* 录用状态枚举
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public enum AdmitStatus {
|
||||
|
||||
/** 录用 */
|
||||
ADMITTED("录用", "已录用该候选人"),
|
||||
|
||||
/** 未录用 */
|
||||
NOT_ADMITTED("未录用", "未录用该候选人"),
|
||||
|
||||
/** 放弃 */
|
||||
WITHDRAWN("放弃", "候选人放弃");
|
||||
|
||||
private final String code;
|
||||
private final String desc;
|
||||
|
||||
AdmitStatus(String code, String desc) {
|
||||
this.code = code;
|
||||
this.desc = desc;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public String getDesc() {
|
||||
return desc;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据编码获取描述
|
||||
*/
|
||||
public static String getDescByCode(String code) {
|
||||
for (AdmitStatus status : values()) {
|
||||
if (status.getCode().equals(code)) {
|
||||
return status.getDesc();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,157 @@
|
||||
package com.ruoyi.ccdi.handler;
|
||||
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
import com.alibaba.excel.write.handler.SheetWriteHandler;
|
||||
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
|
||||
import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder;
|
||||
import com.ruoyi.common.annotation.Required;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.poi.ss.usermodel.*;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* EasyExcel必填字段标注处理器
|
||||
* 在Excel模板生成时,为标注了@Required注解的字段表头添加红色星号(*)标记
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Slf4j
|
||||
public class RequiredFieldWriteHandler implements SheetWriteHandler {
|
||||
|
||||
/**
|
||||
* 实体类Class对象
|
||||
*/
|
||||
private final Class<?> modelClass;
|
||||
|
||||
/**
|
||||
* 构造函数
|
||||
*
|
||||
* @param modelClass 实体类Class对象
|
||||
*/
|
||||
public RequiredFieldWriteHandler(Class<?> modelClass) {
|
||||
this.modelClass = modelClass;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {
|
||||
// 获取工作表
|
||||
Sheet sheet = writeSheetHolder.getSheet();
|
||||
|
||||
// 获取表头行(第1行,索引为0)
|
||||
Row headerRow = sheet.getRow(0);
|
||||
if (headerRow == null) {
|
||||
log.warn("表头行不存在,跳过必填字段标注");
|
||||
return;
|
||||
}
|
||||
|
||||
// 创建红色字体样式
|
||||
Workbook workbook = writeWorkbookHolder.getWorkbook();
|
||||
CellStyle redStyle = createRedFontStyle(workbook);
|
||||
|
||||
// 解析实体类中的必填字段
|
||||
Set<Integer> requiredColumns = parseRequiredFields();
|
||||
|
||||
// 为必填字段的表头添加红色星号
|
||||
for (Integer columnIndex : requiredColumns) {
|
||||
Cell cell = headerRow.getCell(columnIndex);
|
||||
if (cell != null) {
|
||||
String originalValue = cell.getStringCellValue();
|
||||
// 添加红色星号
|
||||
cell.setCellValue(originalValue + "*");
|
||||
// 应用红色样式到星号
|
||||
cell.setCellStyle(redStyle);
|
||||
log.info("为列[{}]的表头添加必填标记(*)", columnIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建红色字体样式
|
||||
*
|
||||
* @param workbook 工作簿
|
||||
* @return 单元格样式
|
||||
*/
|
||||
private CellStyle createRedFontStyle(Workbook workbook) {
|
||||
CellStyle style = workbook.createCellStyle();
|
||||
|
||||
// 设置字体为红色
|
||||
Font font = workbook.createFont();
|
||||
font.setColor(IndexedColors.RED.getIndex());
|
||||
font.setBold(true);
|
||||
style.setFont(font);
|
||||
|
||||
// 设置对齐方式
|
||||
style.setAlignment(HorizontalAlignment.CENTER);
|
||||
style.setVerticalAlignment(VerticalAlignment.CENTER);
|
||||
|
||||
// 设置边框
|
||||
style.setBorderTop(BorderStyle.THIN);
|
||||
style.setBorderBottom(BorderStyle.THIN);
|
||||
style.setBorderLeft(BorderStyle.THIN);
|
||||
style.setBorderRight(BorderStyle.THIN);
|
||||
|
||||
return style;
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析实体类中的必填字段
|
||||
*
|
||||
* @return 必填字段的列索引集合
|
||||
*/
|
||||
private Set<Integer> parseRequiredFields() {
|
||||
Set<Integer> result = new HashSet<>();
|
||||
|
||||
// 获取所有字段(包括父类的)
|
||||
List<Field> fields = getAllFields(modelClass);
|
||||
|
||||
for (Field field : fields) {
|
||||
// 检查是否有@Required注解
|
||||
Required required = field.getAnnotation(Required.class);
|
||||
if (required == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// 获取列索引
|
||||
Integer columnIndex = getColumnIndex(field);
|
||||
if (columnIndex == null) {
|
||||
log.warn("字段[{}]没有指定@ExcelProperty的index,跳过必填标记", field.getName());
|
||||
continue;
|
||||
}
|
||||
|
||||
result.add(columnIndex);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取类的所有字段(包括父类的)
|
||||
*
|
||||
* @param clazz 类对象
|
||||
* @return 字段列表
|
||||
*/
|
||||
private List<Field> getAllFields(Class<?> clazz) {
|
||||
List<Field> fields = new ArrayList<>();
|
||||
while (clazz != null && clazz != Object.class) {
|
||||
fields.addAll(Arrays.asList(clazz.getDeclaredFields()));
|
||||
clazz = clazz.getSuperclass();
|
||||
}
|
||||
return fields;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取字段对应的列索引
|
||||
*
|
||||
* @param field 字段对象
|
||||
* @return 列索引
|
||||
*/
|
||||
private Integer getColumnIndex(Field field) {
|
||||
ExcelProperty excelProperty = field.getAnnotation(ExcelProperty.class);
|
||||
if (excelProperty != null && excelProperty.index() >= 0) {
|
||||
return excelProperty.index();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package com.ruoyi.ccdi.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.ruoyi.ccdi.domain.CcdiStaffRecruitment;
|
||||
import com.ruoyi.ccdi.domain.dto.CcdiStaffRecruitmentQueryDTO;
|
||||
import com.ruoyi.ccdi.domain.vo.CcdiStaffRecruitmentVO;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 员工招聘信息 数据层
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-02-05
|
||||
*/
|
||||
public interface CcdiStaffRecruitmentMapper extends BaseMapper<CcdiStaffRecruitment> {
|
||||
|
||||
/**
|
||||
* 分页查询招聘信息列表
|
||||
*
|
||||
* @param page 分页对象
|
||||
* @param queryDTO 查询条件
|
||||
* @return 招聘信息VO分页结果
|
||||
*/
|
||||
Page<CcdiStaffRecruitmentVO> selectRecruitmentPage(@Param("page") Page<CcdiStaffRecruitmentVO> page,
|
||||
@Param("query") CcdiStaffRecruitmentQueryDTO queryDTO);
|
||||
|
||||
/**
|
||||
* 查询招聘信息详情
|
||||
*
|
||||
* @param recruitId 招聘项目编号
|
||||
* @return 招聘信息VO
|
||||
*/
|
||||
CcdiStaffRecruitmentVO selectRecruitmentById(@Param("recruitId") String recruitId);
|
||||
|
||||
/**
|
||||
* 批量插入招聘信息数据
|
||||
*
|
||||
* @param list 招聘信息列表
|
||||
* @return 插入行数
|
||||
*/
|
||||
int insertBatch(@Param("list") List<CcdiStaffRecruitment> list);
|
||||
|
||||
/**
|
||||
* 批量更新招聘信息数据
|
||||
*
|
||||
* @param list 招聘信息列表
|
||||
* @return 更新行数
|
||||
*/
|
||||
int updateBatch(@Param("list") List<CcdiStaffRecruitment> list);
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
package com.ruoyi.ccdi.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.ruoyi.ccdi.domain.dto.CcdiStaffRecruitmentAddDTO;
|
||||
import com.ruoyi.ccdi.domain.dto.CcdiStaffRecruitmentEditDTO;
|
||||
import com.ruoyi.ccdi.domain.dto.CcdiStaffRecruitmentQueryDTO;
|
||||
import com.ruoyi.ccdi.domain.excel.CcdiStaffRecruitmentExcel;
|
||||
import com.ruoyi.ccdi.domain.vo.CcdiStaffRecruitmentVO;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 员工招聘信息 服务层
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-02-05
|
||||
*/
|
||||
public interface ICcdiStaffRecruitmentService {
|
||||
|
||||
/**
|
||||
* 查询招聘信息列表
|
||||
*
|
||||
* @param queryDTO 查询条件
|
||||
* @return 招聘信息VO集合
|
||||
*/
|
||||
List<CcdiStaffRecruitmentVO> selectRecruitmentList(CcdiStaffRecruitmentQueryDTO queryDTO);
|
||||
|
||||
/**
|
||||
* 分页查询招聘信息列表
|
||||
*
|
||||
* @param page 分页对象
|
||||
* @param queryDTO 查询条件
|
||||
* @return 招聘信息VO分页结果
|
||||
*/
|
||||
Page<CcdiStaffRecruitmentVO> selectRecruitmentPage(Page<CcdiStaffRecruitmentVO> page, CcdiStaffRecruitmentQueryDTO queryDTO);
|
||||
|
||||
/**
|
||||
* 查询招聘信息列表(用于导出)
|
||||
*
|
||||
* @param queryDTO 查询条件
|
||||
* @return 招聘信息Excel实体集合
|
||||
*/
|
||||
List<CcdiStaffRecruitmentExcel> selectRecruitmentListForExport(CcdiStaffRecruitmentQueryDTO queryDTO);
|
||||
|
||||
/**
|
||||
* 查询招聘信息详情
|
||||
*
|
||||
* @param recruitId 招聘项目编号
|
||||
* @return 招聘信息VO
|
||||
*/
|
||||
CcdiStaffRecruitmentVO selectRecruitmentById(String recruitId);
|
||||
|
||||
/**
|
||||
* 新增招聘信息
|
||||
*
|
||||
* @param addDTO 新增DTO
|
||||
* @return 结果
|
||||
*/
|
||||
int insertRecruitment(CcdiStaffRecruitmentAddDTO addDTO);
|
||||
|
||||
/**
|
||||
* 修改招聘信息
|
||||
*
|
||||
* @param editDTO 编辑DTO
|
||||
* @return 结果
|
||||
*/
|
||||
int updateRecruitment(CcdiStaffRecruitmentEditDTO editDTO);
|
||||
|
||||
/**
|
||||
* 批量删除招聘信息
|
||||
*
|
||||
* @param recruitIds 需要删除的招聘项目编号
|
||||
* @return 结果
|
||||
*/
|
||||
int deleteRecruitmentByIds(String[] recruitIds);
|
||||
|
||||
/**
|
||||
* 导入招聘信息数据
|
||||
*
|
||||
* @param excelList Excel实体列表
|
||||
* @param isUpdateSupport 是否更新支持
|
||||
* @return 结果
|
||||
*/
|
||||
String importRecruitment(List<CcdiStaffRecruitmentExcel> excelList, Boolean isUpdateSupport);
|
||||
}
|
||||
@@ -0,0 +1,322 @@
|
||||
package com.ruoyi.ccdi.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.ruoyi.ccdi.domain.CcdiStaffRecruitment;
|
||||
import com.ruoyi.ccdi.domain.dto.CcdiStaffRecruitmentAddDTO;
|
||||
import com.ruoyi.ccdi.domain.dto.CcdiStaffRecruitmentEditDTO;
|
||||
import com.ruoyi.ccdi.domain.dto.CcdiStaffRecruitmentQueryDTO;
|
||||
import com.ruoyi.ccdi.domain.excel.CcdiStaffRecruitmentExcel;
|
||||
import com.ruoyi.ccdi.domain.vo.CcdiStaffRecruitmentVO;
|
||||
import com.ruoyi.ccdi.enums.AdmitStatus;
|
||||
import com.ruoyi.ccdi.mapper.CcdiStaffRecruitmentMapper;
|
||||
import com.ruoyi.ccdi.service.ICcdiStaffRecruitmentService;
|
||||
import com.ruoyi.common.utils.IdCardUtil;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 员工招聘信息 服务层处理
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-02-05
|
||||
*/
|
||||
@Service
|
||||
public class CcdiStaffRecruitmentServiceImpl implements ICcdiStaffRecruitmentService {
|
||||
|
||||
@Resource
|
||||
private CcdiStaffRecruitmentMapper recruitmentMapper;
|
||||
|
||||
/**
|
||||
* 查询招聘信息列表
|
||||
*
|
||||
* @param queryDTO 查询条件
|
||||
* @return 招聘信息VO集合
|
||||
*/
|
||||
@Override
|
||||
public List<CcdiStaffRecruitmentVO> selectRecruitmentList(CcdiStaffRecruitmentQueryDTO queryDTO) {
|
||||
Page<CcdiStaffRecruitmentVO> page = new Page<>(1, Integer.MAX_VALUE);
|
||||
Page<CcdiStaffRecruitmentVO> resultPage = recruitmentMapper.selectRecruitmentPage(page, queryDTO);
|
||||
return resultPage.getRecords();
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页查询招聘信息列表
|
||||
*
|
||||
* @param page 分页对象
|
||||
* @param queryDTO 查询条件
|
||||
* @return 招聘信息VO分页结果
|
||||
*/
|
||||
@Override
|
||||
public Page<CcdiStaffRecruitmentVO> selectRecruitmentPage(Page<CcdiStaffRecruitmentVO> page, CcdiStaffRecruitmentQueryDTO queryDTO) {
|
||||
Page<CcdiStaffRecruitmentVO> resultPage = recruitmentMapper.selectRecruitmentPage(page, queryDTO);
|
||||
|
||||
// 设置录用状态描述
|
||||
resultPage.getRecords().forEach(vo ->
|
||||
vo.setAdmitStatusDesc(AdmitStatus.getDescByCode(vo.getAdmitStatus()))
|
||||
);
|
||||
|
||||
return resultPage;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询招聘信息列表(用于导出)
|
||||
*
|
||||
* @param queryDTO 查询条件
|
||||
* @return 招聘信息Excel实体集合
|
||||
*/
|
||||
@Override
|
||||
public List<CcdiStaffRecruitmentExcel> selectRecruitmentListForExport(CcdiStaffRecruitmentQueryDTO queryDTO) {
|
||||
Page<CcdiStaffRecruitmentVO> page = new Page<>(1, Integer.MAX_VALUE);
|
||||
Page<CcdiStaffRecruitmentVO> resultPage = recruitmentMapper.selectRecruitmentPage(page, queryDTO);
|
||||
|
||||
return resultPage.getRecords().stream().map(vo -> {
|
||||
CcdiStaffRecruitmentExcel excel = new CcdiStaffRecruitmentExcel();
|
||||
BeanUtils.copyProperties(vo, excel);
|
||||
return excel;
|
||||
}).toList();
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询招聘信息详情
|
||||
*
|
||||
* @param recruitId 招聘项目编号
|
||||
* @return 招聘信息VO
|
||||
*/
|
||||
@Override
|
||||
public CcdiStaffRecruitmentVO selectRecruitmentById(String recruitId) {
|
||||
CcdiStaffRecruitmentVO vo = recruitmentMapper.selectRecruitmentById(recruitId);
|
||||
if (vo != null) {
|
||||
vo.setAdmitStatusDesc(AdmitStatus.getDescByCode(vo.getAdmitStatus()));
|
||||
}
|
||||
return vo;
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增招聘信息
|
||||
*
|
||||
* @param addDTO 新增DTO
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
@Transactional
|
||||
public int insertRecruitment(CcdiStaffRecruitmentAddDTO addDTO) {
|
||||
// 检查招聘项目编号唯一性
|
||||
if (recruitmentMapper.selectById(addDTO.getRecruitId()) != null) {
|
||||
throw new RuntimeException("该招聘项目编号已存在");
|
||||
}
|
||||
|
||||
CcdiStaffRecruitment recruitment = new CcdiStaffRecruitment();
|
||||
BeanUtils.copyProperties(addDTO, recruitment);
|
||||
int result = recruitmentMapper.insert(recruitment);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改招聘信息
|
||||
*
|
||||
* @param editDTO 编辑DTO
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
@Transactional
|
||||
public int updateRecruitment(CcdiStaffRecruitmentEditDTO editDTO) {
|
||||
CcdiStaffRecruitment recruitment = new CcdiStaffRecruitment();
|
||||
BeanUtils.copyProperties(editDTO, recruitment);
|
||||
int result = recruitmentMapper.updateById(recruitment);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量删除招聘信息
|
||||
*
|
||||
* @param recruitIds 需要删除的招聘项目编号
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
@Transactional
|
||||
public int deleteRecruitmentByIds(String[] recruitIds) {
|
||||
return recruitmentMapper.deleteBatchIds(List.of(recruitIds));
|
||||
}
|
||||
|
||||
/**
|
||||
* 导入招聘信息数据(批量优化版本)
|
||||
*
|
||||
* @param excelList Excel实体列表
|
||||
* @param isUpdateSupport 是否更新支持,true-存在则更新,false-存在则跳过
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
@Transactional
|
||||
public String importRecruitment(List<CcdiStaffRecruitmentExcel> excelList, Boolean isUpdateSupport) {
|
||||
if (StringUtils.isNull(excelList) || excelList.isEmpty()) {
|
||||
return "至少需要一条数据";
|
||||
}
|
||||
|
||||
int successNum = 0;
|
||||
int failureNum = 0;
|
||||
StringBuilder successMsg = new StringBuilder();
|
||||
StringBuilder failureMsg = new StringBuilder();
|
||||
|
||||
// 第一阶段:数据验证和分类
|
||||
List<CcdiStaffRecruitment> toInsertList = new ArrayList<>();
|
||||
List<CcdiStaffRecruitment> toUpdateList = new ArrayList<>();
|
||||
|
||||
// 批量收集所有招聘项目编号
|
||||
List<String> recruitIds = new ArrayList<>();
|
||||
|
||||
for (CcdiStaffRecruitmentExcel excel : excelList) {
|
||||
if (StringUtils.isNotEmpty(excel.getRecruitId())) {
|
||||
recruitIds.add(excel.getRecruitId());
|
||||
}
|
||||
}
|
||||
|
||||
// 批量查询已存在的招聘项目编号
|
||||
Map<String, CcdiStaffRecruitment> existingRecruitmentMap = new HashMap<>();
|
||||
if (!recruitIds.isEmpty()) {
|
||||
LambdaQueryWrapper<CcdiStaffRecruitment> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.in(CcdiStaffRecruitment::getRecruitId, recruitIds);
|
||||
List<CcdiStaffRecruitment> existingRecruitments = recruitmentMapper.selectList(wrapper);
|
||||
existingRecruitmentMap = existingRecruitments.stream()
|
||||
.collect(Collectors.toMap(CcdiStaffRecruitment::getRecruitId, r -> r));
|
||||
}
|
||||
|
||||
// 第二阶段:处理每条数据
|
||||
for (int i = 0; i < excelList.size(); i++) {
|
||||
CcdiStaffRecruitmentExcel excel = excelList.get(i);
|
||||
try {
|
||||
// 验证必填字段和数据格式
|
||||
validateRecruitmentDataBasic(excel);
|
||||
|
||||
CcdiStaffRecruitment recruitment = new CcdiStaffRecruitment();
|
||||
BeanUtils.copyProperties(excel, recruitment);
|
||||
|
||||
// 检查是否已存在
|
||||
CcdiStaffRecruitment existingRecruitment = existingRecruitmentMap.get(excel.getRecruitId());
|
||||
|
||||
// 判断数据状态和操作类型
|
||||
if (existingRecruitment != null) {
|
||||
// 招聘项目编号已存在
|
||||
if (isUpdateSupport) {
|
||||
// 支持更新,添加到更新列表
|
||||
recruitment.setUpdatedBy("导入");
|
||||
toUpdateList.add(recruitment);
|
||||
} else {
|
||||
// 不支持更新,跳过或报错
|
||||
throw new RuntimeException("该招聘项目编号已存在");
|
||||
}
|
||||
} else {
|
||||
// 招聘项目编号不存在,新增数据
|
||||
recruitment.setCreatedBy("导入");
|
||||
toInsertList.add(recruitment);
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
failureNum++;
|
||||
failureMsg.append("<br/>").append(failureNum).append("、招聘项目编号 ").append(excel.getRecruitId())
|
||||
.append(" 导入失败:").append(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
// 第三阶段:批量执行数据库操作
|
||||
if (!toInsertList.isEmpty()) {
|
||||
// 使用自定义批量插入方法
|
||||
recruitmentMapper.insertBatch(toInsertList);
|
||||
successNum += toInsertList.size();
|
||||
}
|
||||
|
||||
if (!toUpdateList.isEmpty()) {
|
||||
// 使用自定义批量更新方法
|
||||
recruitmentMapper.updateBatch(toUpdateList);
|
||||
successNum += toUpdateList.size();
|
||||
}
|
||||
|
||||
// 第四阶段:返回结果(只返回错误信息)
|
||||
if (failureNum > 0) {
|
||||
failureMsg.insert(0, "很抱歉,导入完成!成功 " + successNum + " 条,失败 " + failureNum + " 条,错误如下:");
|
||||
throw new RuntimeException(failureMsg.toString());
|
||||
} else {
|
||||
successMsg.insert(0, "恭喜您,数据已全部导入成功!共 " + successNum + " 条,数据类型:");
|
||||
if (!toInsertList.isEmpty()) {
|
||||
successMsg.append("新增 ").append(toInsertList.size()).append(" 条");
|
||||
}
|
||||
if (!toUpdateList.isEmpty()) {
|
||||
if (!toInsertList.isEmpty()) {
|
||||
successMsg.append(",");
|
||||
}
|
||||
successMsg.append("更新 ").append(toUpdateList.size()).append(" 条");
|
||||
}
|
||||
return successMsg.toString();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证招聘信息数据(仅基本字段验证,不进行数据库查询)
|
||||
*/
|
||||
private void validateRecruitmentDataBasic(CcdiStaffRecruitmentExcel excel) {
|
||||
// 验证必填字段
|
||||
if (StringUtils.isEmpty(excel.getRecruitId())) {
|
||||
throw new RuntimeException("招聘项目编号不能为空");
|
||||
}
|
||||
if (StringUtils.isEmpty(excel.getRecruitName())) {
|
||||
throw new RuntimeException("招聘项目名称不能为空");
|
||||
}
|
||||
if (StringUtils.isEmpty(excel.getPosName())) {
|
||||
throw new RuntimeException("职位名称不能为空");
|
||||
}
|
||||
if (StringUtils.isEmpty(excel.getPosCategory())) {
|
||||
throw new RuntimeException("职位类别不能为空");
|
||||
}
|
||||
if (StringUtils.isEmpty(excel.getPosDesc())) {
|
||||
throw new RuntimeException("职位描述不能为空");
|
||||
}
|
||||
if (StringUtils.isEmpty(excel.getCandName())) {
|
||||
throw new RuntimeException("应聘人员姓名不能为空");
|
||||
}
|
||||
if (StringUtils.isEmpty(excel.getCandEdu())) {
|
||||
throw new RuntimeException("应聘人员学历不能为空");
|
||||
}
|
||||
if (StringUtils.isEmpty(excel.getCandId())) {
|
||||
throw new RuntimeException("证件号码不能为空");
|
||||
}
|
||||
if (StringUtils.isEmpty(excel.getCandSchool())) {
|
||||
throw new RuntimeException("应聘人员毕业院校不能为空");
|
||||
}
|
||||
if (StringUtils.isEmpty(excel.getCandMajor())) {
|
||||
throw new RuntimeException("应聘人员专业不能为空");
|
||||
}
|
||||
if (StringUtils.isEmpty(excel.getCandGrad())) {
|
||||
throw new RuntimeException("应聘人员毕业年月不能为空");
|
||||
}
|
||||
if (StringUtils.isEmpty(excel.getAdmitStatus())) {
|
||||
throw new RuntimeException("录用情况不能为空");
|
||||
}
|
||||
|
||||
// 验证证件号码格式
|
||||
String idCardError = IdCardUtil.getErrorMessage(excel.getCandId());
|
||||
if (idCardError != null) {
|
||||
throw new RuntimeException("证件号码" + idCardError);
|
||||
}
|
||||
|
||||
// 验证毕业年月格式(YYYYMM)
|
||||
if (!excel.getCandGrad().matches("^((19|20)\\d{2})(0[1-9]|1[0-2])$")) {
|
||||
throw new RuntimeException("毕业年月格式不正确,应为YYYYMM");
|
||||
}
|
||||
|
||||
// 验证录用状态
|
||||
if (AdmitStatus.getDescByCode(excel.getAdmitStatus()) == null) {
|
||||
throw new RuntimeException("录用情况只能填写'录用'、'未录用'或'放弃'");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
<?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.ccdi.mapper.CcdiStaffRecruitmentMapper">
|
||||
|
||||
<!-- 招聘信息ResultMap -->
|
||||
<resultMap type="com.ruoyi.ccdi.domain.vo.CcdiStaffRecruitmentVO" id="CcdiStaffRecruitmentVOResult">
|
||||
<id property="recruitId" column="recruit_id"/>
|
||||
<result property="recruitName" column="recruit_name"/>
|
||||
<result property="posName" column="pos_name"/>
|
||||
<result property="posCategory" column="pos_category"/>
|
||||
<result property="posDesc" column="pos_desc"/>
|
||||
<result property="candName" column="cand_name"/>
|
||||
<result property="candEdu" column="cand_edu"/>
|
||||
<result property="candId" column="cand_id"/>
|
||||
<result property="candSchool" column="cand_school"/>
|
||||
<result property="candMajor" column="cand_major"/>
|
||||
<result property="candGrad" column="cand_grad"/>
|
||||
<result property="admitStatus" column="admit_status"/>
|
||||
<result property="interviewerName1" column="interviewer_name1"/>
|
||||
<result property="interviewerId1" column="interviewer_id1"/>
|
||||
<result property="interviewerName2" column="interviewer_name2"/>
|
||||
<result property="interviewerId2" column="interviewer_id2"/>
|
||||
<result property="createdBy" column="created_by"/>
|
||||
<result property="createTime" column="create_time"/>
|
||||
<result property="updatedBy" column="updated_by"/>
|
||||
<result property="updateTime" column="update_time"/>
|
||||
</resultMap>
|
||||
|
||||
<!-- 分页查询招聘信息列表 -->
|
||||
<select id="selectRecruitmentPage" resultMap="CcdiStaffRecruitmentVOResult">
|
||||
SELECT
|
||||
recruit_id, recruit_name, pos_name, pos_category, pos_desc,
|
||||
cand_name, cand_edu, cand_id, cand_school, cand_major, cand_grad,
|
||||
admit_status, interviewer_name1, interviewer_id1, interviewer_name2, interviewer_id2,
|
||||
created_by, create_time, updated_by, update_time
|
||||
FROM ccdi_staff_recruitment
|
||||
<where>
|
||||
<if test="query.recruitName != null and query.recruitName != ''">
|
||||
AND recruit_name LIKE CONCAT('%', #{query.recruitName}, '%')
|
||||
</if>
|
||||
<if test="query.posName != null and query.posName != ''">
|
||||
AND pos_name LIKE CONCAT('%', #{query.posName}, '%')
|
||||
</if>
|
||||
<if test="query.candName != null and query.candName != ''">
|
||||
AND cand_name LIKE CONCAT('%', #{query.candName}, '%')
|
||||
</if>
|
||||
<if test="query.candId != null and query.candId != ''">
|
||||
AND cand_id = #{query.candId}
|
||||
</if>
|
||||
<if test="query.admitStatus != null and query.admitStatus != ''">
|
||||
AND admit_status = #{query.admitStatus}
|
||||
</if>
|
||||
<if test="query.interviewerName != null and query.interviewerName != ''">
|
||||
AND (interviewer_name1 LIKE CONCAT('%', #{query.interviewerName}, '%')
|
||||
OR interviewer_name2 LIKE CONCAT('%', #{query.interviewerName}, '%'))
|
||||
</if>
|
||||
<if test="query.interviewerId != null and query.interviewerId != ''">
|
||||
AND (interviewer_id1 = #{query.interviewerId}
|
||||
OR interviewer_id2 = #{query.interviewerId})
|
||||
</if>
|
||||
</where>
|
||||
ORDER BY create_time DESC
|
||||
</select>
|
||||
|
||||
<!-- 查询招聘信息详情 -->
|
||||
<select id="selectRecruitmentById" resultMap="CcdiStaffRecruitmentVOResult">
|
||||
SELECT
|
||||
recruit_id, recruit_name, pos_name, pos_category, pos_desc,
|
||||
cand_name, cand_edu, cand_id, cand_school, cand_major, cand_grad,
|
||||
admit_status, interviewer_name1, interviewer_id1, interviewer_name2, interviewer_id2,
|
||||
created_by, create_time, updated_by, update_time
|
||||
FROM ccdi_staff_recruitment
|
||||
WHERE recruit_id = #{recruitId}
|
||||
</select>
|
||||
|
||||
<!-- 批量插入招聘信息数据 -->
|
||||
<insert id="insertBatch">
|
||||
INSERT INTO ccdi_staff_recruitment
|
||||
(recruit_id, recruit_name, pos_name, pos_category, pos_desc,
|
||||
cand_name, cand_edu, cand_id, cand_school, cand_major, cand_grad,
|
||||
admit_status, interviewer_name1, interviewer_id1, interviewer_name2, interviewer_id2,
|
||||
created_by, create_time, updated_by, update_time)
|
||||
VALUES
|
||||
<foreach collection="list" item="item" separator=",">
|
||||
(#{item.recruitId}, #{item.recruitName}, #{item.posName}, #{item.posCategory}, #{item.posDesc},
|
||||
#{item.candName}, #{item.candEdu}, #{item.candId}, #{item.candSchool}, #{item.candMajor}, #{item.candGrad},
|
||||
#{item.admitStatus}, #{item.interviewerName1}, #{item.interviewerId1}, #{item.interviewerName2}, #{item.interviewerId2},
|
||||
#{item.createdBy}, NOW(), #{item.updatedBy}, NOW())
|
||||
</foreach>
|
||||
</insert>
|
||||
|
||||
<!-- 批量更新招聘信息数据 -->
|
||||
<update id="updateBatch">
|
||||
<foreach collection="list" item="item" separator=";">
|
||||
UPDATE ccdi_staff_recruitment
|
||||
SET recruit_name = #{item.recruitName},
|
||||
pos_name = #{item.posName},
|
||||
pos_category = #{item.posCategory},
|
||||
pos_desc = #{item.posDesc},
|
||||
cand_name = #{item.candName},
|
||||
cand_edu = #{item.candEdu},
|
||||
cand_id = #{item.candId},
|
||||
cand_school = #{item.candSchool},
|
||||
cand_major = #{item.candMajor},
|
||||
cand_grad = #{item.candGrad},
|
||||
admit_status = #{item.admitStatus},
|
||||
interviewer_name1 = #{item.interviewerName1},
|
||||
interviewer_id1 = #{item.interviewerId1},
|
||||
interviewer_name2 = #{item.interviewerName2},
|
||||
interviewer_id2 = #{item.interviewerId2},
|
||||
updated_by = #{item.updatedBy},
|
||||
update_time = NOW()
|
||||
WHERE recruit_id = #{item.recruitId}
|
||||
</foreach>
|
||||
</update>
|
||||
|
||||
</mapper>
|
||||
Reference in New Issue
Block a user