入职任务预览,入职任务cope,验证填入的信息
This commit is contained in:
+295
@@ -0,0 +1,295 @@
|
||||
namespace SimpleAdmin.Application;
|
||||
|
||||
/// <summary>
|
||||
/// 统一校验并规范化员工端固定入职信息。
|
||||
/// </summary>
|
||||
internal static class OnboardingEmployeeInfoValidator
|
||||
{
|
||||
private static readonly int[] IdCardWeights =
|
||||
{
|
||||
7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2
|
||||
};
|
||||
|
||||
private static readonly char[] IdCardCheckCodes =
|
||||
{
|
||||
'1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// 规范化文本,并校验固定登记表字段的格式。
|
||||
/// </summary>
|
||||
public static void ValidateAndNormalize(ObTaskEmployeeInfo input)
|
||||
{
|
||||
input.EmployeeName = input.EmployeeName?.Trim();
|
||||
input.Phone = input.Phone?.Trim();
|
||||
input.Email = input.Email?.Trim();
|
||||
input.IdCardNumber = input.IdCardNumber?.Trim().ToUpperInvariant();
|
||||
input.BankCardNumber = global::System.Text.RegularExpressions.Regex.Replace(
|
||||
input.BankCardNumber ?? string.Empty,
|
||||
"[\\s-]",
|
||||
string.Empty);
|
||||
input.BankName = input.BankName?.Trim();
|
||||
input.BankAccountName = input.EmployeeName;
|
||||
|
||||
if (string.IsNullOrWhiteSpace(input.EmployeeName) || input.EmployeeName.Length > 100)
|
||||
throw Oops.Bah("员工姓名不能为空且不能超过 100 个字符");
|
||||
|
||||
if (input.Gender != "男" && input.Gender != "女")
|
||||
throw Oops.Bah("请选择正确的性别");
|
||||
|
||||
if (!global::System.Text.RegularExpressions.Regex.IsMatch(
|
||||
input.Phone ?? string.Empty,
|
||||
"^1[3-9]\\d{9}$"))
|
||||
{
|
||||
throw Oops.Bah("请输入正确的 11 位手机号码");
|
||||
}
|
||||
|
||||
if (!TryValidateIdCard(input.IdCardNumber, out var idCardBirthday, out var idCardError))
|
||||
throw Oops.Bah(idCardError);
|
||||
|
||||
ValidateBirthday(input.Birthday, idCardBirthday);
|
||||
ValidateOptionalEmail(input.Email);
|
||||
ValidateOptionalNumber(input.Height, "身高", 100M, 250M, "厘米");
|
||||
ValidateOptionalNumber(input.Weight, "体重", 30M, 300M, "公斤");
|
||||
ValidateBankCard(input.BankCardNumber);
|
||||
|
||||
if (string.IsNullOrWhiteSpace(input.BankName) || input.BankName.Length > 100)
|
||||
throw Oops.Bah("开户银行名称不能为空且不能超过 100 个字符");
|
||||
|
||||
ValidateOptionalContactPhone(input.EmergencyPhone);
|
||||
ValidateEducationHistory(input.EducationHistoryJson);
|
||||
ValidateWorkHistory(input.WorkHistoryJson);
|
||||
ValidateFamilyMembers(input.FamilyMembersJson);
|
||||
ValidateJson(input.CustomVariablesJson, global::System.Text.Json.JsonValueKind.Object, "员工补充变量");
|
||||
}
|
||||
|
||||
private static bool TryValidateIdCard(
|
||||
string idCardNumber,
|
||||
out DateTime birthday,
|
||||
out string errorMessage)
|
||||
{
|
||||
birthday = default;
|
||||
errorMessage = null;
|
||||
|
||||
var structureIsValid = global::System.Text.RegularExpressions.Regex.IsMatch(
|
||||
idCardNumber ?? string.Empty,
|
||||
"^\\d{17}[0-9X]$");
|
||||
if (!structureIsValid)
|
||||
{
|
||||
errorMessage = "请输入正确的 18 位身份证号码";
|
||||
return false;
|
||||
}
|
||||
|
||||
var birthdayText = idCardNumber.Substring(6, 8);
|
||||
var birthdayIsValid = DateTime.TryParseExact(
|
||||
birthdayText,
|
||||
"yyyyMMdd",
|
||||
global::System.Globalization.CultureInfo.InvariantCulture,
|
||||
global::System.Globalization.DateTimeStyles.None,
|
||||
out birthday);
|
||||
if (!birthdayIsValid || birthday.Date > DateTime.Today)
|
||||
{
|
||||
errorMessage = "身份证号码中的出生日期不正确";
|
||||
return false;
|
||||
}
|
||||
|
||||
var total = 0;
|
||||
for (var index = 0; index < IdCardWeights.Length; index++)
|
||||
{
|
||||
total += (idCardNumber[index] - '0') * IdCardWeights[index];
|
||||
}
|
||||
|
||||
if (IdCardCheckCodes[total % 11] == idCardNumber[17])
|
||||
return true;
|
||||
|
||||
errorMessage = "身份证号码校验位不正确";
|
||||
return false;
|
||||
}
|
||||
|
||||
private static void ValidateBirthday(string birthdayText, DateTime idCardBirthday)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(birthdayText))
|
||||
return;
|
||||
|
||||
var birthdayIsValid = DateTime.TryParseExact(
|
||||
birthdayText.Trim(),
|
||||
"yyyy-MM-dd",
|
||||
global::System.Globalization.CultureInfo.InvariantCulture,
|
||||
global::System.Globalization.DateTimeStyles.None,
|
||||
out var birthday);
|
||||
if (!birthdayIsValid || birthday.Date > DateTime.Today)
|
||||
throw Oops.Bah("请输入正确的出生日期");
|
||||
|
||||
if (birthday.Date != idCardBirthday.Date)
|
||||
throw Oops.Bah("出生日期与身份证号码不一致");
|
||||
}
|
||||
|
||||
private static void ValidateOptionalEmail(string email)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(email))
|
||||
return;
|
||||
|
||||
var emailIsValid = email.Length <= 100
|
||||
&& global::System.Net.Mail.MailAddress.TryCreate(email, out _);
|
||||
if (!emailIsValid)
|
||||
throw Oops.Bah("请输入正确的电子邮箱");
|
||||
}
|
||||
|
||||
private static void ValidateOptionalNumber(
|
||||
string value,
|
||||
string fieldName,
|
||||
decimal min,
|
||||
decimal max,
|
||||
string unit)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(value))
|
||||
return;
|
||||
|
||||
var numberIsValid = decimal.TryParse(
|
||||
value.Trim(),
|
||||
global::System.Globalization.NumberStyles.Number,
|
||||
global::System.Globalization.CultureInfo.InvariantCulture,
|
||||
out var number);
|
||||
if (!numberIsValid || number < min || number > max)
|
||||
{
|
||||
throw Oops.Bah($"{fieldName}应为 {min:0} 至 {max:0} {unit}之间的数字");
|
||||
}
|
||||
}
|
||||
|
||||
private static void ValidateBankCard(string bankCardNumber)
|
||||
{
|
||||
var bankCardIsValid = global::System.Text.RegularExpressions.Regex.IsMatch(
|
||||
bankCardNumber ?? string.Empty,
|
||||
"^\\d{12,19}$");
|
||||
if (!bankCardIsValid)
|
||||
throw Oops.Bah("请输入 12 至 19 位银行卡号");
|
||||
}
|
||||
|
||||
private static void ValidateOptionalContactPhone(string phone)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(phone))
|
||||
return;
|
||||
|
||||
var contactPhoneIsValid = global::System.Text.RegularExpressions.Regex.IsMatch(
|
||||
phone.Trim(),
|
||||
"^(1[3-9]\\d{9}|0\\d{2,3}-?\\d{7,8})$");
|
||||
if (!contactPhoneIsValid)
|
||||
throw Oops.Bah("请输入正确的紧急联系人手机号码或座机号码");
|
||||
}
|
||||
|
||||
private static void ValidateEducationHistory(string json)
|
||||
{
|
||||
ValidateHistoryRows(json, "教育经历", (row, rowNumber) =>
|
||||
{
|
||||
GetRequiredRowValue(row, "timeRange", rowNumber, "教育经历", "时间范围");
|
||||
GetRequiredRowValue(row, "location", rowNumber, "教育经历", "学校或机构");
|
||||
GetRequiredRowValue(row, "content", rowNumber, "教育经历", "专业或学习内容");
|
||||
GetRequiredRowValue(row, "result", rowNumber, "教育经历", "结果或学位");
|
||||
});
|
||||
}
|
||||
|
||||
private static void ValidateWorkHistory(string json)
|
||||
{
|
||||
ValidateHistoryRows(json, "工作经历", (row, rowNumber) =>
|
||||
{
|
||||
GetRequiredRowValue(row, "timeRange", rowNumber, "工作经历", "起止时间");
|
||||
GetRequiredRowValue(row, "companyName", rowNumber, "工作经历", "工作单位");
|
||||
GetRequiredRowValue(row, "position", rowNumber, "工作经历", "担任职务");
|
||||
GetRequiredRowValue(row, "leaveReason", rowNumber, "工作经历", "离职原因");
|
||||
});
|
||||
}
|
||||
|
||||
private static void ValidateFamilyMembers(string json)
|
||||
{
|
||||
ValidateHistoryRows(json, "家庭成员", (row, rowNumber) =>
|
||||
{
|
||||
GetRequiredRowValue(row, "name", rowNumber, "家庭成员", "姓名");
|
||||
GetRequiredRowValue(row, "relationship", rowNumber, "家庭成员", "关系");
|
||||
var ageText = GetRequiredRowValue(row, "age", rowNumber, "家庭成员", "年龄");
|
||||
var phone = GetRequiredRowValue(row, "phone", rowNumber, "家庭成员", "联系电话");
|
||||
|
||||
var ageIsValid = int.TryParse(ageText, out var age) && age >= 0 && age <= 120;
|
||||
if (!ageIsValid)
|
||||
throw Oops.Bah($"第 {rowNumber} 条家庭成员的年龄应为 0 至 120 之间的整数");
|
||||
|
||||
var phoneIsValid = global::System.Text.RegularExpressions.Regex.IsMatch(
|
||||
phone,
|
||||
"^(1[3-9]\\d{9}|0\\d{2,3}-?\\d{7,8})$");
|
||||
if (!phoneIsValid)
|
||||
throw Oops.Bah($"第 {rowNumber} 条家庭成员的联系电话格式不正确");
|
||||
});
|
||||
}
|
||||
|
||||
private static void ValidateHistoryRows(
|
||||
string json,
|
||||
string fieldName,
|
||||
Action<global::System.Text.Json.JsonElement, int> validateRow)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(json))
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
using var document = global::System.Text.Json.JsonDocument.Parse(json);
|
||||
if (document.RootElement.ValueKind != global::System.Text.Json.JsonValueKind.Array)
|
||||
throw new global::System.Text.Json.JsonException();
|
||||
|
||||
var rowNumber = 0;
|
||||
foreach (var row in document.RootElement.EnumerateArray())
|
||||
{
|
||||
rowNumber++;
|
||||
if (row.ValueKind != global::System.Text.Json.JsonValueKind.Object)
|
||||
throw Oops.Bah($"第 {rowNumber} 条{fieldName}格式不正确,请删除后重新添加");
|
||||
|
||||
validateRow(row, rowNumber);
|
||||
}
|
||||
}
|
||||
catch (global::System.Text.Json.JsonException)
|
||||
{
|
||||
throw Oops.Bah($"{fieldName}格式不正确,请刷新页面后重新填写");
|
||||
}
|
||||
}
|
||||
|
||||
private static string GetRequiredRowValue(
|
||||
global::System.Text.Json.JsonElement row,
|
||||
string propertyName,
|
||||
int rowNumber,
|
||||
string fieldName,
|
||||
string displayName)
|
||||
{
|
||||
if (!row.TryGetProperty(propertyName, out var property)
|
||||
|| property.ValueKind is global::System.Text.Json.JsonValueKind.Null
|
||||
or global::System.Text.Json.JsonValueKind.Undefined)
|
||||
{
|
||||
throw Oops.Bah($"第 {rowNumber} 条{fieldName}请填写{displayName}");
|
||||
}
|
||||
|
||||
var value = property.ValueKind == global::System.Text.Json.JsonValueKind.String
|
||||
? property.GetString()
|
||||
: property.ToString();
|
||||
if (string.IsNullOrWhiteSpace(value))
|
||||
throw Oops.Bah($"第 {rowNumber} 条{fieldName}请填写{displayName}");
|
||||
|
||||
return value.Trim();
|
||||
}
|
||||
|
||||
private static void ValidateJson(
|
||||
string json,
|
||||
global::System.Text.Json.JsonValueKind expectedKind,
|
||||
string fieldName)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(json))
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
using var document = global::System.Text.Json.JsonDocument.Parse(json);
|
||||
if (document.RootElement.ValueKind != expectedKind)
|
||||
throw new global::System.Text.Json.JsonException();
|
||||
}
|
||||
catch (global::System.Text.Json.JsonException)
|
||||
{
|
||||
throw Oops.Bah($"{fieldName}格式不正确,请刷新页面后重新填写");
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user