v1.0.38: 邮箱/国内手机号/身份证正则格式校验 - 后端validate.php(接入person add/update、duplicate_check账号校验、soft_update、hard_add/convert)前端common.js三函数+person/media/fragment表单提交校验

This commit is contained in:
nanguaboss
2026-08-09 22:58:36 +08:00
parent 4ff4349ef5
commit 3a5cdcdd36
12 changed files with 112 additions and 1 deletions
+8
View File
@@ -10,6 +10,8 @@
* - 企业名称 name_zh 或 display_name 任一相同即重复
*/
require_once __DIR__ . '/db.php';
require_once __DIR__ . '/response.php';
require_once __DIR__ . '/validate.php';
/** 字段中文名 */
const DUP_LABELS = [
@@ -191,6 +193,12 @@ function checkSingleAccountDuplicate(PDO $pdo, $platform, $accountId, $profileUr
$platform = trim((string)$platform);
$accountId = trim((string)$accountId);
if ($platform !== '' && $accountId !== '') {
// 格式校验:手机/邮箱平台必须符合对应格式
if ($platform === 'phone') {
checkFieldFormat('phone', $accountId);
} elseif ($platform === 'email') {
checkFieldFormat('email', $accountId);
}
if ($platform === 'phone' || $platform === 'email') {
$dup = findDuplicate($pdo, $platform, $accountId, $excludeIds);
} else {
+55
View File
@@ -0,0 +1,55 @@
<?php
/**
* 格式校验(2026-08-09)
* 邮箱 / 国内手机号码 / 身份证号码 正则验证
*/
/** 国内手机号码:11 位,1 开头,第二位 3-9 */
function validatePhoneCN($v)
{
return (bool)preg_match('/^1[3-9]\d{9}$/', trim((string)$v));
}
/** 邮箱 */
function validateEmail($v)
{
return (bool)preg_match('/^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$/', trim((string)$v));
}
/** 身份证号码:15 位 或 18 位(末位可为 X/x) */
function validateIdCard($v)
{
return (bool)preg_match('/^\d{15}$|^\d{17}[\dXx]$/', trim((string)$v));
}
/**
* 统一格式校验:不合法时直接返回错误响应
* @param string $type phone|email|id_number
* @param string $value
* @param bool $allowEmpty 空值是否放行(默认 true:未填不校验)
*/
function checkFieldFormat($type, $value, $allowEmpty = true)
{
$value = trim((string)$value);
if ($value === '') {
return $allowEmpty;
}
switch ($type) {
case 'phone':
if (!validatePhoneCN($value)) {
Response::error('手机号码格式不正确(应为国内 11 位手机号,如 13812345678)', 400);
}
break;
case 'email':
if (!validateEmail($value)) {
Response::error('邮箱格式不正确', 400);
}
break;
case 'id_number':
if (!validateIdCard($value)) {
Response::error('身份证号码格式不正确(应为 15 或 18 位)', 400);
}
break;
}
return true;
}
+5
View File
@@ -10,6 +10,7 @@ require_once __DIR__ . '/../common/db.php';
require_once __DIR__ . '/../common/response.php';
require_once __DIR__ . '/../common/auth.php';
require_once __DIR__ . '/../common/logger.php';
require_once __DIR__ . '/../common/validate.php';
checkAjax();
checkPermission('preliminary');
@@ -30,6 +31,10 @@ if ($sourceChannel === '') {
$sourceChannel = '手动录入';
}
// 格式校验:手机 / 邮箱
checkFieldFormat('phone', $phone);
checkFieldFormat('email', $email);
// 至少有一项内容才能录为碎片
if ($companyName === '' && $personName === '' && $phone === '' && $email === '' && $category === '' && $description === '') {
Response::error('请至少填写一项内容', 400);
+5
View File
@@ -12,6 +12,7 @@ require_once __DIR__ . '/../common/auth.php';
require_once __DIR__ . '/../common/logger.php';
require_once __DIR__ . '/../common/completeness.php';
require_once __DIR__ . '/../common/duplicate_check.php';
require_once __DIR__ . '/../common/validate.php';
checkAjax();
checkPermission('preliminary');
@@ -45,6 +46,10 @@ $sourceChannel = $frag['source_channel'] ?? null;
$convertedId = 0;
// 格式校验:手机 / 邮箱
checkFieldFormat('phone', $phone);
checkFieldFormat('email', $email);
// 唯一性校验:按目标类型,收集全部重复
$dups = [];
if ($targetType === 'company' && $companyName !== '') {
+11
View File
@@ -12,6 +12,7 @@ require_once __DIR__ . '/../common/logger.php';
require_once __DIR__ . '/../common/helpers.php';
require_once __DIR__ . '/../common/completeness.php';
require_once __DIR__ . '/../common/duplicate_check.php';
require_once __DIR__ . '/../common/validate.php';
checkAjax();
checkPermission('preliminary');
@@ -57,6 +58,16 @@ switch ($table) {
'graduated_from' => 's', 'hometown' => 's', 'work_location' => 's',
'id_type' => 's', 'id_number' => 's', 'source_channel' => 's', 'source_detail' => 's',
]);
// 格式校验:身份证 / 手机 / 邮箱
if (!empty($fields['id_number'])) {
checkFieldFormat('id_number', $fields['id_number']);
}
if (isset($_POST['phone'])) {
checkFieldFormat('phone', $_POST['phone']);
}
if (isset($_POST['email'])) {
checkFieldFormat('email', $_POST['email']);
}
// 唯一性校验(排除自身):身份证 / 手机 / 邮箱
$dups = [];
if (!empty($fields['id_number'])) {
+2
View File
@@ -11,6 +11,7 @@ require_once __DIR__ . '/../common/logger.php';
require_once __DIR__ . '/../common/helpers.php';
require_once __DIR__ . '/../common/completeness.php';
require_once __DIR__ . '/../common/duplicate_check.php';
require_once __DIR__ . '/../common/validate.php';
checkAjax();
checkPermission('person');
@@ -35,6 +36,7 @@ if ((int)$chk->fetchColumn() > 0) {
// 唯一性校验:身份证号码 / 联系方式(手机/邮箱/社媒账号/主页链接),收集全部重复
$dups = [];
if (!empty($data['id_number'])) {
checkFieldFormat('id_number', $data['id_number']);
$dup = findDuplicate($pdo, 'id_number', $data['id_number']);
if ($dup) $dups[] = $dup;
}
+2
View File
@@ -10,6 +10,7 @@ require_once __DIR__ . '/../common/logger.php';
require_once __DIR__ . '/../common/helpers.php';
require_once __DIR__ . '/../common/completeness.php';
require_once __DIR__ . '/../common/duplicate_check.php';
require_once __DIR__ . '/../common/validate.php';
checkAjax();
checkPermission('person');
@@ -33,6 +34,7 @@ if (!$old) {
// 唯一性校验(排除自身):身份证号码 / 联系方式,收集全部重复
$dups = [];
if (!empty($data['id_number'])) {
checkFieldFormat('id_number', $data['id_number']);
$dup = findDuplicate($pdo, 'id_number', $data['id_number'], [$id]);
if ($dup) $dups[] = $dup;
}