入职申请 根据姓名生成公司邮箱账号

This commit is contained in:
dxfeng 2025-07-29 09:52:42 +08:00
parent c72bbd6f4d
commit b4835fc6a9
4 changed files with 468 additions and 0 deletions

View File

@ -0,0 +1,89 @@
package com.weaver.seconddev.portal.action.entry;
import cn.hutool.core.convert.Convert;
import com.weaver.common.base.entity.result.WeaResult;
import com.weaver.esb.api.rpc.EsbServerlessRpcRemoteInterface;
import com.weaver.seconddev.portal.entity.param.BaseParam;
import com.weaver.seconddev.portal.mapper.action.entry.EmailAccountGenerateMapper;
import com.weaver.seconddev.portal.util.ChineseNameToPinyin;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.HashMap;
import java.util.Map;
/**
* @author:dxfeng
* @createTime: 2025/07/28
* @version: 1.0
*/
@Slf4j
@Service("emailAccountGenerateAction")
public class EmailAccountGenerateAction implements EsbServerlessRpcRemoteInterface {
private static final String EMAIL_DOMAIN = "@chabaidao.com";
@Autowired
EmailAccountGenerateMapper emailAccountGenerateMapper;
BaseParam baseParam = new BaseParam();
@Override
public WeaResult<Map<String, Object>> execute(Map<String, Object> params) {
// 获取参数
String xm = Convert.toStr(params.get("xm"), "");
Long requestId = Convert.toLong(params.get("requestId"));
if (StringUtils.isBlank(xm)) {
return WeaResult.fail("姓名不能为空", true);
}
// 生成基础邮箱账号
String pinyinName = ChineseNameToPinyin.convertChineseNameToPinyin(xm);
// 检查并生成唯一邮箱账号
String uniqueEmail = generateUniqueEmail(pinyinName, requestId);
Map<String, Object> dataMap = new HashMap<>();
// 将生成的邮箱账号放入返回结果中
dataMap.put("email", uniqueEmail);
return WeaResult.success(dataMap);
}
/**
* 生成唯一的邮箱账号
*
* @param pinyinName 拼音姓名
* @return 唯一邮箱账号
*/
private String generateUniqueEmail(String pinyinName, Long requestId) {
String baseEmail = pinyinName + EMAIL_DOMAIN;
// 首先检查基础邮箱是否已存在
if (!isEmailExists(baseEmail,requestId)) {
return baseEmail;
}
// 如果基础邮箱已存在则尝试添加数字后缀
int suffix = 1;
String emailWithSuffix;
do {
emailWithSuffix = pinyinName + suffix + EMAIL_DOMAIN;
suffix++;
} while (isEmailExists(emailWithSuffix, requestId));
return emailWithSuffix;
}
/**
* 检查邮箱是否已存在
*
* @param email 邮箱账号
* @return 是否存在
*/
private boolean isEmailExists(String email, Long requestId) {
Integer checkCount = emailAccountGenerateMapper.checkSameEmailAccount(baseParam, email, requestId);
return checkCount != null && checkCount > 0;
}
}

View File

@ -0,0 +1,16 @@
package com.weaver.seconddev.portal.mapper.action.entry;
import com.weaver.seconddev.portal.entity.param.BaseParam;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
/**
* @author:dxfeng
* @createTime: 2025/07/28
* @version: 1.0
*/
@Mapper
public interface EmailAccountGenerateMapper {
Integer checkSameEmailAccount(@Param("param") BaseParam param, @Param("email") String email, @Param("requestId") Long requestId);
}

View File

@ -0,0 +1,349 @@
package com.weaver.seconddev.portal.util;
import net.sourceforge.pinyin4j.PinyinHelper;
import net.sourceforge.pinyin4j.format.HanyuPinyinCaseType;
import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat;
import net.sourceforge.pinyin4j.format.HanyuPinyinToneType;
import net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombination;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
/**
* 中文姓名转拼音工具类
* 支持多音字识别复姓处理姓名结构分析等
*/
public class ChineseNameToPinyin {
// 拼音输出格式
private static final HanyuPinyinOutputFormat FORMAT = new HanyuPinyinOutputFormat();
// 姓氏多音字映射姓氏位置读音
private static final Map<String, String> SURNAME_POLYPHONE_MAP = new HashMap<>();
// 非姓氏多音字映射词中/词尾读音
private static final Map<String, String> NON_SURNAME_POLYPHONE_MAP = new HashMap<>();
// 常见复姓
private static final Set<String> COMPOUND_SURNAMES = new HashSet<>();
// 常见单姓
private static final Set<String> SINGLE_SURNAMES = new HashSet<>();
// 常用汉字读音修正表用于处理常见错误拼音
private static final Map<String, String> COMMON_CORRECTION_MAP = new HashMap<>();
// 缓存已处理过的姓名提高性能
private static final Map<String, String> NAME_CACHE = new ConcurrentHashMap<>();
private static final int MAX_CACHE_SIZE = 10000;
static {
FORMAT.setCaseType(HanyuPinyinCaseType.LOWERCASE);
FORMAT.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
// 初始化姓氏多音字映射
initSurnamePolyphoneMap();
// 初始化非姓氏多音字映射
initNonSurnamePolyphoneMap();
// 初始化复姓列表
initCompoundSurnames();
// 初始化单姓列表
initSingleSurnames();
// 初始化常用汉字读音修正表
initCommonCorrectionMap();
}
/**
* 初始化姓氏多音字映射
*/
private static void initSurnamePolyphoneMap() {
// 姓氏中的多音字在姓氏位置的特殊读音
SURNAME_POLYPHONE_MAP.put("", "ou");
SURNAME_POLYPHONE_MAP.put("", "qiu");
SURNAME_POLYPHONE_MAP.put("", "shan");
SURNAME_POLYPHONE_MAP.put("", "xie");
SURNAME_POLYPHONE_MAP.put("", "hua");
SURNAME_POLYPHONE_MAP.put("", "piao");
SURNAME_POLYPHONE_MAP.put("", "zeng");
SURNAME_POLYPHONE_MAP.put("", "zha");
SURNAME_POLYPHONE_MAP.put("", "zhai");
SURNAME_POLYPHONE_MAP.put("", "yu");
SURNAME_POLYPHONE_MAP.put("", "ge");
SURNAME_POLYPHONE_MAP.put("", "miao");
SURNAME_POLYPHONE_MAP.put("", "qin");
SURNAME_POLYPHONE_MAP.put("", "mi");
SURNAME_POLYPHONE_MAP.put("", "she");
SURNAME_POLYPHONE_MAP.put("", "po");
SURNAME_POLYPHONE_MAP.put("", "yun");
SURNAME_POLYPHONE_MAP.put("", "shao");
SURNAME_POLYPHONE_MAP.put("", "kui");
SURNAME_POLYPHONE_MAP.put("", "qin");
SURNAME_POLYPHONE_MAP.put("", "xian");
SURNAME_POLYPHONE_MAP.put("", "tan");
}
/**
* 初始化非姓氏多音字映射
*/
private static void initNonSurnamePolyphoneMap() {
// 非姓氏位置的多音字读音
NON_SURNAME_POLYPHONE_MAP.put("", "qu");
NON_SURNAME_POLYPHONE_MAP.put("", "chou");
NON_SURNAME_POLYPHONE_MAP.put("", "dan");
NON_SURNAME_POLYPHONE_MAP.put("", "jie");
NON_SURNAME_POLYPHONE_MAP.put("", "hua");
NON_SURNAME_POLYPHONE_MAP.put("", "pu");
NON_SURNAME_POLYPHONE_MAP.put("", "ceng");
NON_SURNAME_POLYPHONE_MAP.put("", "cha");
NON_SURNAME_POLYPHONE_MAP.put("", "di");
NON_SURNAME_POLYPHONE_MAP.put("", "wei");
NON_SURNAME_POLYPHONE_MAP.put("", "gai");
NON_SURNAME_POLYPHONE_MAP.put("", "miu");
NON_SURNAME_POLYPHONE_MAP.put("", "tan");
NON_SURNAME_POLYPHONE_MAP.put("", "fu");
NON_SURNAME_POLYPHONE_MAP.put("", "zhe");
NON_SURNAME_POLYPHONE_MAP.put("", "fan");
NON_SURNAME_POLYPHONE_MAP.put("", "yuan");
NON_SURNAME_POLYPHONE_MAP.put("", "zhao");
NON_SURNAME_POLYPHONE_MAP.put("", "wei");
NON_SURNAME_POLYPHONE_MAP.put("", "xiǎn");
NON_SURNAME_POLYPHONE_MAP.put("", "qín");
}
/**
* 初始化复姓列表
*/
private static void initCompoundSurnames() {
// 常见复姓按长度排序长的在前
String[] compoundSurnames = {
"欧阳", "太史", "端木", "上官", "司马", "东方", "独孤", "南宫", "万俟", "闻人",
"夏侯", "诸葛", "尉迟", "公羊", "赫连", "澹台", "皇甫", "宗政", "濮阳", "公冶",
"太叔", "申屠", "公孙", "慕容", "仲孙", "钟离", "长孙", "宇文", "司徒", "鲜于",
"司空", "闾丘", "子车", "亓官", "司寇", "巫马", "公西", "颛孙", "壤驷", "公良",
"漆雕", "乐正", "宰父", "谷梁", "拓跋", "夹谷", "轩辕", "令狐", "段干", "百里",
"呼延", "东郭", "南门", "羊舌", "微生", "岳父", "缑亢", "况后", "有琴", "梁丘",
"左丘", "东门", "西门"
};
COMPOUND_SURNAMES.addAll(Arrays.asList(compoundSurnames));
}
/**
* 初始化单姓列表
*/
private static void initSingleSurnames() {
// 常见单姓按频率排序
String[] singleSurnames = {
"", "", "", "", "", "", "", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "", "", ""
};
SINGLE_SURNAMES.addAll(Arrays.asList(singleSurnames));
}
/**
* 初始化常用汉字读音修正表
*/
private static void initCommonCorrectionMap() {
// 常见汉字读音修正
COMMON_CORRECTION_MAP.put("", "qian"); // 作为名字时通常读作qian
COMMON_CORRECTION_MAP.put("", "peng"); // 人名常用字
COMMON_CORRECTION_MAP.put("", "zhe"); // 人名常用字
}
/**
* 将中文姓名转换为拼音不带声调
*
* @param chineseName 中文姓名
* @return 拼音全称
*/
public static String convertChineseNameToPinyin(String chineseName) {
if (chineseName == null || chineseName.isEmpty()) {
return "";
}
// 先从缓存中查找
String cachedResult = NAME_CACHE.get(chineseName);
if (cachedResult != null) {
return cachedResult;
}
String result = doConvertChineseNameToPinyin(chineseName);
// 缓存结果控制缓存大小
if (NAME_CACHE.size() < MAX_CACHE_SIZE) {
NAME_CACHE.put(chineseName, result);
}
return result;
}
/**
* 实际转换逻辑
*/
private static String doConvertChineseNameToPinyin(String chineseName) {
StringBuilder pinyinBuilder = new StringBuilder();
int i = 0;
// 首先尝试匹配复姓
boolean surnameProcessed = false;
if (chineseName.length() >= 2) {
// 优先匹配3字复姓
if (chineseName.length() >= 3) {
String threeCharSurname = chineseName.substring(0, 3);
if (COMPOUND_SURNAMES.contains(threeCharSurname)) {
processSurname(pinyinBuilder, threeCharSurname);
i = 3;
surnameProcessed = true;
}
}
// 如果不是3字复姓再匹配2字复姓
if (!surnameProcessed) {
String twoCharSurname = chineseName.substring(0, 2);
if (COMPOUND_SURNAMES.contains(twoCharSurname)) {
processSurname(pinyinBuilder, twoCharSurname);
i = 2;
surnameProcessed = true;
}
}
}
// 如果不是复姓处理单姓
if (!surnameProcessed && chineseName.length() >= 1) {
String firstChar = String.valueOf(chineseName.charAt(0));
if (SINGLE_SURNAMES.contains(firstChar) || SURNAME_POLYPHONE_MAP.containsKey(firstChar)) {
processSurname(pinyinBuilder, firstChar);
i = 1;
}
}
// 处理剩余部分名字
while (i < chineseName.length()) {
char ch = chineseName.charAt(i);
processNonSurname(pinyinBuilder, ch, i, chineseName);
i++;
}
return pinyinBuilder.toString();
}
/**
* 处理姓氏部分
*/
private static void processSurname(StringBuilder pinyinBuilder, String surname) {
for (int j = 0; j < surname.length(); j++) {
char ch = surname.charAt(j);
String pinyin = getPinyinWithPolyphone(ch, true, j, surname);
pinyinBuilder.append(pinyin);
}
}
/**
* 处理非姓氏部分
*/
private static void processNonSurname(StringBuilder pinyinBuilder, char ch, int position, String fullName) {
// 处理空格等非中文字符
if (ch == ' ') {
pinyinBuilder.append(" ");
return;
}
// 处理英文字母
if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')) {
pinyinBuilder.append(Character.toLowerCase(ch));
return;
}
// 处理数字
if (ch >= '0' && ch <= '9') {
pinyinBuilder.append(ch);
return;
}
// 处理中文字符
String pinyin = getPinyinWithPolyphone(ch, false, position, fullName);
pinyinBuilder.append(pinyin);
}
/**
* 获取字符的拼音考虑多音字
*/
private static String getPinyinWithPolyphone(char ch, boolean isSurname, int position, String context) {
try {
// 首先检查常用修正表
String correction = COMMON_CORRECTION_MAP.get(String.valueOf(ch));
if (correction != null) {
return correction;
}
// 检查多音字映射
if (isSurname) {
String surnamePinyin = SURNAME_POLYPHONE_MAP.get(String.valueOf(ch));
if (surnamePinyin != null) {
return surnamePinyin;
}
} else {
String nonSurnamePinyin = NON_SURNAME_POLYPHONE_MAP.get(String.valueOf(ch));
if (nonSurnamePinyin != null) {
return nonSurnamePinyin;
}
}
// 使用pinyin4j获取拼音
String[] pinyinArray = PinyinHelper.toHanyuPinyinStringArray(ch, FORMAT);
if (pinyinArray != null && pinyinArray.length > 0) {
return pinyinArray[0]; // 默认返回第一个拼音
} else {
return String.valueOf(ch); // 非中文字符返回原字符
}
} catch (BadHanyuPinyinOutputFormatCombination e) {
return String.valueOf(ch); // 异常情况下返回原字符
}
}
/**
* 带分隔符的拼音转换
*
* @param chineseName 中文姓名
* @param separator 分隔符
* @return 带分隔符的拼音
*/
public static String convertChineseNameToPinyinWithSeparator(String chineseName, String separator) {
String pinyin = convertChineseNameToPinyin(chineseName);
if (pinyin.isEmpty()) {
return "";
}
StringBuilder result = new StringBuilder();
for (int i = 0; i < pinyin.length(); i++) {
if (i > 0) {
result.append(separator);
}
result.append(pinyin.charAt(i));
}
return result.toString();
}
/**
* 清空缓存
*/
public static void clearCache() {
NAME_CACHE.clear();
}
/**
* 获取缓存大小
*/
public static int getCacheSize() {
return NAME_CACHE.size();
}
}

View File

@ -0,0 +1,14 @@
<?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.weaver.seconddev.portal.mapper.action.entry.EmailAccountGenerateMapper">
<select id="checkSameEmailAccount" resultType="java.lang.Integer">
select count(t1.id) from ${param.e10_common}.uf_jcl_rzsq t1
where t1.tenant_key = #{param.tenantKey}
<!-- and t1.delete_type = 0-->
and t1.email = #{email}
<if test="requestId != null and requestId != ''">
and t1.form_data_id != #{requestId}
</if>
</select>
</mapper>