2026-01-09 20:13:01 +08:00
|
|
|
|
package com.ruoyi.cms.util;
|
|
|
|
|
|
|
|
|
|
|
|
import com.ruoyi.common.utils.StringUtils;
|
2026-05-20 16:10:46 +08:00
|
|
|
|
import org.apache.commons.lang3.ObjectUtils;
|
2026-01-09 20:13:01 +08:00
|
|
|
|
|
|
|
|
|
|
import javax.servlet.http.HttpServletRequest;
|
2026-05-20 16:10:46 +08:00
|
|
|
|
import java.time.LocalDate;
|
|
|
|
|
|
import java.time.Period;
|
|
|
|
|
|
import java.time.format.DateTimeFormatter;
|
2026-01-09 20:13:01 +08:00
|
|
|
|
import java.util.ArrayList;
|
|
|
|
|
|
import java.util.Arrays;
|
|
|
|
|
|
import java.util.List;
|
|
|
|
|
|
import java.util.Objects;
|
|
|
|
|
|
import java.util.stream.Collectors;
|
|
|
|
|
|
|
|
|
|
|
|
public class StringUtil {
|
|
|
|
|
|
|
|
|
|
|
|
/*1101(求职者)、1102(招聘者)、1103(网格员)、1104(内部工作者)*/
|
|
|
|
|
|
public static final Long COMPANY_ADMIN_ROLE_KEY = 1102L;
|
|
|
|
|
|
|
|
|
|
|
|
/************************移动端角色开始***************************/
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 移动端-企业用户
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static final String IS_COMPANY_USER = "0";
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 移动端-求职者
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static final String IS_JOB_REQUEST_USER = "1";
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 移动端-网格员
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static final String IS_GRID_USER = "2";
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 移动端-内部工作者
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static final String IS_INTERNAL_USER = "3";
|
|
|
|
|
|
/************************移动端角色结束***************************/
|
|
|
|
|
|
/**
|
|
|
|
|
|
* pc端-求职者
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static final String SYS_QZZ = "1101";
|
|
|
|
|
|
/**
|
|
|
|
|
|
* pc端-企业
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static final String SYS_QY = "1102";
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 互联网用户头
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static final String USER_KEY="hlw_";
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 岗位互联网
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static final String BASE_WW_GW="https://www.xjksly.cn/kashi/job-portal/detail/";
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
*录用
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static final String HIRE_LY="0";
|
|
|
|
|
|
|
2026-05-29 14:24:05 +08:00
|
|
|
|
/**
|
|
|
|
|
|
*不录用
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static final String HIRE_LY_NOT="2";
|
|
|
|
|
|
|
2026-01-09 20:13:01 +08:00
|
|
|
|
/**
|
|
|
|
|
|
*录用-系统
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static final String HIRE_SOURCE_SYSTEM="0";
|
|
|
|
|
|
/**
|
|
|
|
|
|
*录用-招聘会
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static final String HIRE_SOURCE_ZPH="1";
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 标记
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static final boolean PATH_TEST_ENV = true;
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 测试环境附件地址
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static final String PATH_DEV = "http://ks.zhaopinzao8dian.com/file/";
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 正式环境环境地址
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static final String PATH_PROXY_37 = "http://10.98.80.37/file/";
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 互联网
|
|
|
|
|
|
*/
|
2026-06-03 15:16:41 +08:00
|
|
|
|
public static final String PATH_PROXY_50="http://39.98.44.136:6024/data/file/";
|
2026-01-09 20:13:01 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 经办端
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static final String PATH_PROXY_146="http://10.98.80.146/file/";
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 身份证规则
|
|
|
|
|
|
*/
|
|
|
|
|
|
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 Boolean isEmptyOrNull(String s){
|
|
|
|
|
|
if(Objects.isNull(s)){return true;}
|
|
|
|
|
|
return s.isEmpty();
|
|
|
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 将逗号分隔的数字字符串转换为List<Integer>
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static List<Integer> convertStringToIntegerList(String input) {
|
|
|
|
|
|
if (isEmptyOrNull(input)) {
|
|
|
|
|
|
return new ArrayList<>();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return Arrays.stream(input.split(",")) // 按逗号分割字符串
|
|
|
|
|
|
.map(String::trim) // 去除每个部分的前后空格
|
|
|
|
|
|
.map(Integer::parseInt) // 将字符串转换为Integer
|
|
|
|
|
|
.collect(Collectors.toList()); // 收集为List
|
|
|
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 将逗号分隔的数字字符串转换为List<Integer>
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static List<Long> convertStringToLongList(String input) {
|
|
|
|
|
|
List<Integer> longs = convertStringToIntegerList(input);
|
|
|
|
|
|
return longs.stream().map(Long::valueOf).collect(Collectors.toList());
|
|
|
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 找到List<Integer>中的最大值
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static Integer findMaxValue(String input) {
|
|
|
|
|
|
List<Integer> numbers = convertStringToIntegerList(input);
|
|
|
|
|
|
if (numbers == null || numbers.isEmpty()) {
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return numbers.stream()
|
|
|
|
|
|
.mapToInt(Integer::intValue) // 将Integer转换为int
|
|
|
|
|
|
.max() // 找到最大值
|
|
|
|
|
|
.orElseThrow(() -> new RuntimeException("列表为空,无法找到最大值")); // 如果列表为空,抛出异常
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public static List<String> convertStringToStringList(String input) {
|
|
|
|
|
|
if (isEmptyOrNull(input)) {
|
|
|
|
|
|
return new ArrayList<>();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return Arrays.stream(input.split(",")) // 按逗号分割字符串
|
|
|
|
|
|
.map(String::trim) // 去除每个部分的前后空格
|
|
|
|
|
|
.collect(Collectors.toList()); // 收集为List
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取附件地址
|
|
|
|
|
|
* @return
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static String getFilePath(HttpServletRequest request){
|
|
|
|
|
|
String proxyServer = getProxyServer(request);
|
|
|
|
|
|
if ("proxy-50".equals(proxyServer)) {
|
|
|
|
|
|
return PATH_PROXY_50;
|
|
|
|
|
|
} else if ("proxy-146".equals(proxyServer)) {
|
|
|
|
|
|
return PATH_PROXY_146;
|
|
|
|
|
|
}
|
|
|
|
|
|
return !PATH_TEST_ENV ? PATH_PROXY_37 : PATH_DEV;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 原方法-不传request
|
|
|
|
|
|
* @return
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static String getFilePath(){
|
|
|
|
|
|
return !PATH_TEST_ENV ? PATH_PROXY_37 : PATH_DEV;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取nginx地址
|
|
|
|
|
|
* @param request
|
|
|
|
|
|
* @return
|
|
|
|
|
|
*/
|
|
|
|
|
|
private static String getProxyServer(HttpServletRequest request) {
|
|
|
|
|
|
if (request == null) {
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
return request.getHeader("X-Proxy-Server");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 手机号脱敏
|
|
|
|
|
|
* @param phone
|
|
|
|
|
|
* @return
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static String desensitizePhone(String phone) {
|
|
|
|
|
|
if (StringUtils.isEmpty(phone) || phone.length() != 11) {
|
|
|
|
|
|
return phone;
|
|
|
|
|
|
}
|
|
|
|
|
|
return phone.replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 脱敏逻辑:前4位 + ***+ 后4位
|
|
|
|
|
|
* @param idCard
|
|
|
|
|
|
* @return
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static String desensitizeIdCard(String idCard) {
|
|
|
|
|
|
if (StringUtils.isEmpty(idCard)) {
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
// 处理18位身份证(支持末尾X/x)
|
|
|
|
|
|
if (idCard.matches("\\d{17}[\\dXx]")) {
|
|
|
|
|
|
return idCard.replaceAll("(\\d{6})\\d{8}([\\dXx]{4})", "$1********$2");
|
|
|
|
|
|
}
|
|
|
|
|
|
// 处理15位身份证
|
|
|
|
|
|
else if (idCard.matches("\\d{15}")) {
|
|
|
|
|
|
return idCard.replaceAll("(\\d{6})\\d{6}(\\d{3})", "$1******$2");
|
|
|
|
|
|
}
|
|
|
|
|
|
// 非标准格式(如16位、含特殊字符):返回部分脱敏(前4位+****+后2位),避免明文暴露
|
|
|
|
|
|
else {
|
|
|
|
|
|
int len = idCard.length();
|
|
|
|
|
|
if (len >= 6) {
|
|
|
|
|
|
return idCard.substring(0, 4) + "****" + idCard.substring(len - 2);
|
|
|
|
|
|
}
|
|
|
|
|
|
// 长度过短(<6位):直接返回***,避免明文
|
|
|
|
|
|
return "***";
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-05-12 13:07:58 +08:00
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 转大写
|
|
|
|
|
|
* @param str
|
|
|
|
|
|
* @return
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static String toUpperCaseIgnoreBlank(String str) {
|
|
|
|
|
|
if (str == null) {
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
String trimmedStr = str.trim();
|
|
|
|
|
|
if (trimmedStr.isEmpty()) {
|
|
|
|
|
|
return str;
|
|
|
|
|
|
}
|
|
|
|
|
|
return str.toUpperCase();
|
|
|
|
|
|
}
|
2026-05-20 16:10:46 +08:00
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 通过身份证获取年龄
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param idNumber
|
|
|
|
|
|
* @return
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static String getAgeByIdNumber(String idNumber) {
|
|
|
|
|
|
if (idNumber == null || idNumber.length() != 18) {
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
//出生日期(yyyyMMdd)
|
|
|
|
|
|
String birthDateStr = idNumber.substring(6, 14);
|
|
|
|
|
|
LocalDate birthDate = LocalDate.parse(birthDateStr, DateTimeFormatter.ofPattern("yyyyMMdd"));
|
|
|
|
|
|
// 年龄
|
|
|
|
|
|
return String.valueOf(Period.between(birthDate, LocalDate.now()).getYears());
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 转换学历至本地学历
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param val
|
|
|
|
|
|
* @return
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static String convertEducation(String val) {
|
|
|
|
|
|
//模型码值
|
|
|
|
|
|
//初中及以下 0 0 小学
|
|
|
|
|
|
//中专/中技 1 1 初中
|
|
|
|
|
|
//高中 2 2 高中
|
|
|
|
|
|
//大专 3 3 中专
|
|
|
|
|
|
//本科 4 4 大专
|
|
|
|
|
|
//硕士 5 5 本科
|
|
|
|
|
|
//博士 6 6 硕士
|
|
|
|
|
|
//MBA/EMBA 7 7 博士
|
|
|
|
|
|
//留学学士 8
|
|
|
|
|
|
//留学硕士 9
|
|
|
|
|
|
//留学博士 10
|
|
|
|
|
|
String result = null;
|
|
|
|
|
|
if (val == null) {
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
if ("0".equals(val) || "1".equals(val)) {//小学,初中-->初中及以下
|
|
|
|
|
|
result = "0";
|
|
|
|
|
|
} else if ("2".equals(val)) {
|
|
|
|
|
|
result = "2";
|
|
|
|
|
|
} else if ("3".equals(val)) {
|
|
|
|
|
|
result = "1";
|
|
|
|
|
|
} else if ("4".equals(val)) {
|
|
|
|
|
|
result = "3";
|
|
|
|
|
|
} else if ("5".equals(val)) {
|
|
|
|
|
|
result = "4";
|
|
|
|
|
|
} else if ("6".equals(val)) {
|
|
|
|
|
|
result = "5";
|
|
|
|
|
|
} else if ("7".equals(val)) {
|
|
|
|
|
|
result = "6";
|
|
|
|
|
|
}
|
|
|
|
|
|
return result;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 工作经验转模型经验
|
|
|
|
|
|
* @param personYearsWorking
|
|
|
|
|
|
* @return
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static String convertExp(Integer personYearsWorking) {
|
|
|
|
|
|
// 实习生 1
|
|
|
|
|
|
// 应届毕业生 2
|
|
|
|
|
|
// 1年以下 3
|
|
|
|
|
|
// 1-3年 4
|
|
|
|
|
|
// 3-5年 5
|
|
|
|
|
|
// 5-10年 6
|
|
|
|
|
|
// 10年以上 7
|
|
|
|
|
|
// 经验不限 0
|
|
|
|
|
|
String modelExp = null;
|
|
|
|
|
|
if (ObjectUtils.isEmpty(personYearsWorking)) {
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (personYearsWorking <= 1) {
|
|
|
|
|
|
modelExp = "3";
|
|
|
|
|
|
} else if (personYearsWorking <= 3) {
|
|
|
|
|
|
modelExp = "4";
|
|
|
|
|
|
} else if (personYearsWorking <= 5) {
|
|
|
|
|
|
modelExp = "5";
|
|
|
|
|
|
} else if (personYearsWorking <= 10) {
|
|
|
|
|
|
modelExp = "6";
|
|
|
|
|
|
} else {
|
|
|
|
|
|
modelExp = "7";
|
|
|
|
|
|
}
|
|
|
|
|
|
return modelExp;
|
|
|
|
|
|
}
|
2026-01-09 20:13:01 +08:00
|
|
|
|
}
|