修改excel上传问题
This commit is contained in:
@@ -2,6 +2,7 @@ package com.ruoyi.cms.domain.vo;
|
||||
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.ruoyi.cms.util.excel.LongConverter;
|
||||
import com.ruoyi.common.annotation.Excel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
@@ -18,12 +19,12 @@ public class JobExcelVo
|
||||
@ApiModelProperty("职位名称")
|
||||
private String jobTitle;
|
||||
|
||||
@ExcelProperty(value = "职位名称", index = 1)
|
||||
@ExcelProperty(value = "职位名称", index = 1,converter = LongConverter.class)
|
||||
@Excel(name = "最小薪资", readConverterExp = "元=")
|
||||
@ApiModelProperty("最小薪资(元)")
|
||||
private Long minSalary;
|
||||
|
||||
@ExcelProperty(value = "职位名称", index = 2)
|
||||
@ExcelProperty(value = "职位名称", index = 2,converter = LongConverter.class)
|
||||
@Excel(name = "最大薪资", readConverterExp = "元=")
|
||||
@ApiModelProperty("最大薪资(元)")
|
||||
private Long maxSalary;
|
||||
@@ -43,7 +44,7 @@ public class JobExcelVo
|
||||
@ApiModelProperty("用人单位名称")
|
||||
private String companyName;
|
||||
|
||||
@ExcelProperty(value = "职位名称", index = 6)
|
||||
@ExcelProperty(value = "职位名称", index = 6,converter = LongConverter.class)
|
||||
@Excel(name = "招聘人数")
|
||||
@ApiModelProperty("招聘人数")
|
||||
private Long vacancies;
|
||||
|
||||
@@ -1193,6 +1193,9 @@ public class JobServiceImpl extends ServiceImpl<JobMapper,Job> implements IJobSe
|
||||
BeanUtils.copyProperties(it, job);
|
||||
//字典转换
|
||||
String education = DictUtils.getDictValue("education", it.getEducation());
|
||||
if (education == null || education.trim().isEmpty()) {
|
||||
education = StringUtil.getEduCodeByDesc(it.getEducation());
|
||||
}
|
||||
String experience = DictUtils.getDictValue("experience", it.getExperience());
|
||||
String jobType = DictUtils.getDictValue("job_type", it.getJobType());
|
||||
String type = DictUtils.getDictValue("position_type", it.getType());
|
||||
@@ -1259,11 +1262,65 @@ public class JobServiceImpl extends ServiceImpl<JobMapper,Job> implements IJobSe
|
||||
continue;
|
||||
}
|
||||
|
||||
List<String> contactNames = StringUtil.splitCellMultiLineData(vo.getContactPerson());
|
||||
List<String> contactPhones = StringUtil.splitContactPhones(vo.getContactPersonPhone());
|
||||
|
||||
if (contactNames.isEmpty() || contactPhones.isEmpty()) {
|
||||
System.out.printf(
|
||||
"警告:岗位【%s】的联系人姓名或手机号为空!姓名:%s,手机号:%s,跳过该组数据%n",
|
||||
matchedJob.getJobTitle(), vo.getContactPerson(), vo.getContactPersonPhone()
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
int nameSize = contactNames.size();
|
||||
int phoneSize = contactPhones.size();
|
||||
int phoneIndex = 0;
|
||||
|
||||
for (int nameIdx = 0; nameIdx < nameSize; nameIdx++) {
|
||||
String currentName = contactNames.get(nameIdx).trim();
|
||||
if (StringUtils.isBlank(currentName)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int phonesForCurrentName;
|
||||
if (nameSize == 1) {
|
||||
phonesForCurrentName = phoneSize - phoneIndex;
|
||||
} else {
|
||||
phonesForCurrentName = 1;
|
||||
}
|
||||
|
||||
// 避免索引越界,修正实际可匹配的手机号数量
|
||||
int actualPhoneCount = Math.min(phonesForCurrentName, phoneSize - phoneIndex);
|
||||
if (actualPhoneCount <= 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
// 为当前姓名分配对应的手机号(1个或多个)
|
||||
for (int p = 0; p < actualPhoneCount; p++) {
|
||||
String currentPhone = contactPhones.get(phoneIndex).trim();
|
||||
if (StringUtils.isBlank(currentPhone)) {
|
||||
phoneIndex++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// 封装联系人数据
|
||||
JobContact contact = new JobContact();
|
||||
contact.setJobId(matchedJob.getJobId());
|
||||
contact.setContactPerson(vo.getContactPerson());
|
||||
contact.setContactPersonPhone(vo.getContactPersonPhone());
|
||||
contact.setContactPerson(currentName);
|
||||
contact.setContactPersonPhone(currentPhone);
|
||||
contactList.add(contact);
|
||||
|
||||
phoneIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
if (phoneIndex < phoneSize) {
|
||||
System.out.printf(
|
||||
"提示:岗位【%s】有 %d 个手机号未分配对应姓名,已忽略%n",
|
||||
matchedJob.getJobTitle(), phoneSize - phoneIndex
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return contactList;
|
||||
|
||||
@@ -3,10 +3,7 @@ package com.ruoyi.cms.util;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class StringUtil {
|
||||
@@ -90,6 +87,30 @@ public class StringUtil {
|
||||
*/
|
||||
public static final String SFZ_VALID_REGEX="^[1-9]\\d{5}(18|19|20)\\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\\d{3}[0-9Xx]$";
|
||||
|
||||
public static final Map<String, String> EDU_DESC_TO_CODE_MAP;
|
||||
|
||||
static {
|
||||
Map<String, String> tempMap = new HashMap<>();
|
||||
tempMap.put("中专及以上", "1");
|
||||
tempMap.put("高中及以上", "2");
|
||||
tempMap.put("大专及以上", "3");
|
||||
tempMap.put("本科及以上", "4");
|
||||
tempMap.put("硕士及以上", "5");
|
||||
EDU_DESC_TO_CODE_MAP = Collections.unmodifiableMap(tempMap);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取学历
|
||||
* @param eduDesc
|
||||
* @return
|
||||
*/
|
||||
public static String getEduCodeByDesc(String eduDesc) {
|
||||
if (eduDesc == null || eduDesc.trim().isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
return EDU_DESC_TO_CODE_MAP.get(eduDesc.trim());
|
||||
}
|
||||
|
||||
public static Boolean isEmptyOrNull(String s){
|
||||
if(Objects.isNull(s)){return true;}
|
||||
return s.isEmpty();
|
||||
@@ -229,4 +250,33 @@ public class StringUtil {
|
||||
}
|
||||
return str.toUpperCase();
|
||||
}
|
||||
|
||||
/**
|
||||
* 工具方法:拆分 Excel 单元格内的多行数据(按换行符拆分)
|
||||
*/
|
||||
public static List<String> splitCellMultiLineData(String cellValue) {
|
||||
if (StringUtils.isBlank(cellValue)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
// 按换行符拆分(兼容 \n 和 \r\n),并过滤空字符串、纯空格字符串
|
||||
return Arrays.stream(cellValue.split("\\r?\\n"))
|
||||
.map(String::trim)
|
||||
.filter(StringUtils::hasText)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 工具方法:拆分联系人手机号(支持换行、逗号分隔,兼容1人多号)
|
||||
*/
|
||||
public static List<String> splitContactPhones(String contactPhoneStr) {
|
||||
if (StringUtils.isBlank(contactPhoneStr)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
// 先按换行符拆分,再按逗号拆分,最后过滤空值和纯空格
|
||||
return Arrays.stream(contactPhoneStr.split("\\r?\\n")) // 处理多行
|
||||
.flatMap(line -> Arrays.stream(line.split(",|,"))) // 处理逗号(中文+英文)
|
||||
.map(String::trim)
|
||||
.filter(StringUtils::hasText)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,140 @@
|
||||
package com.ruoyi.cms.util.excel;
|
||||
|
||||
import com.alibaba.excel.converters.Converter;
|
||||
import com.alibaba.excel.enums.CellDataTypeEnum;
|
||||
import com.alibaba.excel.metadata.GlobalConfiguration;
|
||||
import com.alibaba.excel.metadata.data.ReadCellData;
|
||||
import com.alibaba.excel.metadata.data.WriteCellData;
|
||||
import com.alibaba.excel.metadata.property.ExcelContentProperty;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 最终版 LongConverter:
|
||||
* 1. 正常数字(含单位)→ 正确Long值
|
||||
* 2. 面议/无有效数字 → 返回0
|
||||
* 3. 保留详细日志,便于排查
|
||||
*/
|
||||
public class LongConverter implements Converter<Long> {
|
||||
|
||||
// 需清洗的特殊字符(仅去掉单位/分隔符,保留数字)
|
||||
private static final Set<String> CLEAN_CHARS = new HashSet<String>() {{
|
||||
add("元"); // 金额单位
|
||||
add("/"); // 分隔符
|
||||
add("月"); // 时间单位
|
||||
add(","); // 千分位
|
||||
add("k"); // 千单位
|
||||
add("K"); // 大写K
|
||||
}};
|
||||
|
||||
// 需转换为0的特殊文本(可扩展,比如"无"、"面议"等)
|
||||
private static final Set<String> SPECIAL_TEXT = new HashSet<String>() {{
|
||||
add("面议");
|
||||
add("无");
|
||||
add("面议薪资");
|
||||
add("薪资面议");
|
||||
}};
|
||||
|
||||
@Override
|
||||
public Class<Long> supportJavaTypeKey() {
|
||||
return Long.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CellDataTypeEnum supportExcelTypeKey() {
|
||||
return CellDataTypeEnum.STRING;
|
||||
}
|
||||
|
||||
/**
|
||||
* 读Excel:核心逻辑(适配「面议」转0)
|
||||
*/
|
||||
@Override
|
||||
public Long convertToJavaData(ReadCellData<?> cellData, ExcelContentProperty contentProperty,
|
||||
GlobalConfiguration globalConfiguration) {
|
||||
// 1. 优先获取单元格的字符串值(适配所有EasyExcel版本)
|
||||
String rawValue = null;
|
||||
if (cellData != null) {
|
||||
rawValue = cellData.getStringValue();
|
||||
// 数值型单元格兜底
|
||||
if (StringUtils.isBlank(rawValue) && cellData.getNumberValue() != null) {
|
||||
rawValue = cellData.getNumberValue().toString();
|
||||
}
|
||||
}
|
||||
|
||||
// 2. 空值/空白字符串 → 返回0
|
||||
if (StringUtils.isBlank(rawValue)) {
|
||||
return 0L;
|
||||
}
|
||||
String trimmedValue = rawValue.trim();
|
||||
|
||||
// 3. 匹配"面议"等特殊文本 → 直接返回0
|
||||
if (SPECIAL_TEXT.contains(trimmedValue)) {
|
||||
System.out.printf("【特殊处理】单元格%s,原始值:%s → 转换为0%n",
|
||||
getCellPos(cellData), trimmedValue);
|
||||
return 0L;
|
||||
}
|
||||
|
||||
// 4. 清洗特殊字符(仅去掉单位/分隔符,保留数字)
|
||||
String cleanValue = cleanSpecialChars(trimmedValue);
|
||||
// 清洗后无有效数字 → 返回0
|
||||
if (StringUtils.isBlank(cleanValue)) {
|
||||
System.err.printf("【无有效数字】单元格%s,原始值:%s → 转换为0%n",
|
||||
getCellPos(cellData), trimmedValue);
|
||||
return 0L;
|
||||
}
|
||||
|
||||
// 5. 处理科学计数法
|
||||
cleanValue = handleScientificNotation(cleanValue);
|
||||
|
||||
// 6. 转换为Long(异常则返回0)
|
||||
try {
|
||||
BigDecimal bd = new BigDecimal(cleanValue);
|
||||
// 非整数也转成整数(比如1999.9→1999,或返回0,根据需求选)
|
||||
return bd.longValue(); // 若要严格整数,用longValueExact(),异常时走catch返回0
|
||||
} catch (NumberFormatException e) {
|
||||
System.err.printf("【转换失败】单元格%s,原始值:%s,清洗后:%s,错误:%s → 转换为0%n",
|
||||
getCellPos(cellData), trimmedValue, cleanValue, e.getMessage());
|
||||
return 0L;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 写Excel:Long转字符串
|
||||
*/
|
||||
@Override
|
||||
public WriteCellData<?> convertToExcelData(Long value, ExcelContentProperty contentProperty,
|
||||
GlobalConfiguration globalConfiguration) {
|
||||
if (value == null || value == 0L) {
|
||||
return new WriteCellData<>("面议"); // 导出时0值显示为"面议",可根据需求修改
|
||||
}
|
||||
return new WriteCellData<>(String.valueOf(value));
|
||||
}
|
||||
|
||||
// 辅助方法:清洗特殊字符
|
||||
private String cleanSpecialChars(String value) {
|
||||
String result = value;
|
||||
for (String charToClean : CLEAN_CHARS) {
|
||||
result = result.replace(charToClean, "");
|
||||
}
|
||||
return result.trim();
|
||||
}
|
||||
|
||||
// 辅助方法:处理科学计数法
|
||||
private String handleScientificNotation(String value) {
|
||||
if (StringUtils.isBlank(value) || !value.matches("[+-]?\\d+(\\.\\d+)?[eE][+-]?\\d+")) {
|
||||
return value;
|
||||
}
|
||||
return new BigDecimal(value).toPlainString();
|
||||
}
|
||||
|
||||
// 辅助方法:获取单元格位置(简化日志)
|
||||
private String getCellPos(ReadCellData<?> cellData) {
|
||||
if (cellData == null) {
|
||||
return "未知位置";
|
||||
}
|
||||
return cellData.getRowIndex() + "行" + cellData.getColumnIndex() + "列";
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user