'手机号码', 'email' => '邮箱', 'id_number' => '身份证号码', 'registration_number' => '企业注册号', 'account_id' => '社媒账号ID', 'profile_url' => '主页链接', 'company_name' => '企业名称', ]; /** * 查询 social_accounts 重复记录(phone/email/account_id/profile_url 共用) * @return array|null */ function findSocialDuplicate(PDO $pdo, $where, $params) { $sql = "SELECT sa.id, sa.owner_type, sa.owner_id, COALESCE(p.full_name, c.display_name) AS owner_name FROM social_accounts sa LEFT JOIN persons p ON p.id = sa.owner_id AND sa.owner_type = 'person' LEFT JOIN companies c ON c.id = sa.owner_id AND sa.owner_type = 'company' WHERE $where AND sa.is_active = 1 LIMIT 1"; $stmt = $pdo->prepare($sql); $stmt->execute($params); $row = $stmt->fetch(); if (!$row) { return null; } return $row; } /** * 校验唯一性 * @param PDO $pdo * @param string $type phone|email|id_number|registration_number|account_id|profile_url|company_name * @param string $value 待校验值 * @param array $excludeIds 排除自身记录ID(编辑时;social_accounts 传其 id / persons 传 persons.id / companies 传 companies.id) * @param string|null $platform account_id 类型时必传(同平台内唯一) * @return array|null {label,value,table,id,owner_type,owner_id,name,owner_label,jump} */ function findDuplicate(PDO $pdo, $type, $value, $excludeIds = [], $platform = null) { $value = trim((string)$value); if ($value === '') { return null; } $excludeIds = array_values(array_filter(array_map('intval', (array)$excludeIds))); $excludeSql = ''; $excludeParams = []; if ($excludeIds) { $excludeSql = ' AND id NOT IN (' . implode(',', $excludeIds) . ')'; } switch ($type) { case 'phone': case 'email': $row = findSocialDuplicate($pdo, "sa.platform = ? AND LOWER(sa.account_id) = LOWER(?)" . str_replace('id NOT IN', 'sa.id NOT IN', $excludeSql), array_merge([$type, $value], $excludeParams)); if (!$row) { return null; } return [ 'label' => $type === 'phone' ? '手机号码' : '邮箱', 'value' => $value, 'table' => 'social_accounts', 'id' => (int)$row['id'], 'owner_type' => $row['owner_type'], 'owner_id' => (int)$row['owner_id'], 'name' => $row['owner_name'] ?: ('#' . $row['owner_id']), 'owner_label'=> $row['owner_type'] === 'person' ? '人员' : '企业', 'jump' => 'media.html?id=' . (int)$row['id'], ]; case 'account_id': // 社媒账号:同平台内唯一(phone/email 走专门校验) if ($platform === null || in_array($platform, ['phone', 'email'], true)) { return null; } $row = findSocialDuplicate($pdo, "sa.platform = ? AND LOWER(sa.account_id) = LOWER(?)" . str_replace('id NOT IN', 'sa.id NOT IN', $excludeSql), array_merge([$platform, $value], $excludeParams)); if (!$row) { return null; } return [ 'label' => '社媒账号ID', 'value' => $value, 'table' => 'social_accounts', 'id' => (int)$row['id'], 'owner_type' => $row['owner_type'], 'owner_id' => (int)$row['owner_id'], 'name' => $row['owner_name'] ?: ('#' . $row['owner_id']), 'owner_label'=> $row['owner_type'] === 'person' ? '人员' : '企业', 'jump' => 'media.html?id=' . (int)$row['id'], ]; case 'profile_url': $row = findSocialDuplicate($pdo, "sa.profile_url = ? AND sa.profile_url <> ''" . str_replace('id NOT IN', 'sa.id NOT IN', $excludeSql), array_merge([$value], $excludeParams)); if (!$row) { return null; } return [ 'label' => '主页链接', 'value' => $value, 'table' => 'social_accounts', 'id' => (int)$row['id'], 'owner_type' => $row['owner_type'], 'owner_id' => (int)$row['owner_id'], 'name' => $row['owner_name'] ?: ('#' . $row['owner_id']), 'owner_label'=> $row['owner_type'] === 'person' ? '人员' : '企业', 'jump' => 'media.html?id=' . (int)$row['id'], ]; case 'id_number': $stmt = $pdo->prepare("SELECT id, full_name FROM persons WHERE id_number = ? AND is_active = 1$excludeSql LIMIT 1"); $stmt->execute(array_merge([$value], $excludeParams)); $row = $stmt->fetch(); if (!$row) { return null; } return [ 'label' => '身份证号码', 'value' => $value, 'table' => 'persons', 'id' => (int)$row['id'], 'name' => $row['full_name'] ?: ('#' . $row['id']), 'jump' => 'person.html?id=' . (int)$row['id'], ]; case 'registration_number': $stmt = $pdo->prepare("SELECT id, display_name FROM companies WHERE registration_number = ? AND is_active = 1$excludeSql LIMIT 1"); $stmt->execute(array_merge([$value], $excludeParams)); $row = $stmt->fetch(); if (!$row) { return null; } return [ 'label' => '企业注册号', 'value' => $value, 'table' => 'companies', 'id' => (int)$row['id'], 'name' => $row['display_name'] ?: ('#' . $row['id']), 'jump' => 'company.html?id=' . (int)$row['id'], ]; case 'company_name': $stmt = $pdo->prepare("SELECT id, display_name FROM companies WHERE (name_zh = ? OR display_name = ?) AND is_active = 1$excludeSql LIMIT 1"); $stmt->execute(array_merge([$value, $value], $excludeParams)); $row = $stmt->fetch(); if (!$row) { return null; } return [ 'label' => '企业名称', 'value' => $value, 'table' => 'companies', 'id' => (int)$row['id'], 'name' => $row['display_name'] ?: ('#' . $row['id']), 'jump' => 'company.html?id=' . (int)$row['id'], ]; } return null; } /** * 校验单条账号(媒体模块扁平字段),返回所有重复项数组(空=无重复) * @param PDO $pdo * @param string $platform * @param string $accountId * @param string $profileUrl * @param array $excludeIds * @return array */ function checkSingleAccountDuplicate(PDO $pdo, $platform, $accountId, $profileUrl = '', $excludeIds = []) { $dups = []; $platform = trim((string)$platform); $accountId = trim((string)$accountId); if ($platform !== '' && $accountId !== '') { if ($platform === 'phone' || $platform === 'email') { $dup = findDuplicate($pdo, $platform, $accountId, $excludeIds); } else { $dup = findDuplicate($pdo, 'account_id', $accountId, $excludeIds, $platform); } if ($dup) { $dups[] = $dup; } } $profileUrl = trim((string)$profileUrl); if ($profileUrl !== '') { $dup = findDuplicate($pdo, 'profile_url', $profileUrl, $excludeIds); if ($dup) { $dups[] = $dup; } } return $dups; } /** * 校验联系方式数组(persons/companies 的 contacts/accounts JSON),返回所有重复项数组(空=无重复) * @param PDO $pdo * @param array $accounts [{platform,account_id,profile_url,...}] * @param array $excludeIds 整表替换时排除自身既有账号ID * @return array */ function checkAccountsDuplicates(PDO $pdo, $accounts, $excludeIds = []) { $dups = []; if (!is_array($accounts)) { return $dups; } foreach ($accounts as $a) { if (!is_array($a)) { continue; } $dups = array_merge($dups, checkSingleAccountDuplicate( $pdo, $a['platform'] ?? '', $a['account_id'] ?? '', $a['profile_url'] ?? '', $excludeIds )); } return $dups; }