手机号显示补全国家码格式

This commit is contained in:
meoacgx committed 2025-12-24 02:20:16 +08:00
1 parent cd5a07543e
commit a71417cb32
5 files changed
+109 -11

No files matched your search

@@ -1,6 +1,7 @@
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using TelegramPanel.Core.Interfaces;
using TelegramPanel.Core.Utils;
using TelegramPanel.Data.Entities;
using TelegramPanel.Data.Repositories;
@@ -36,36 +37,52 @@ public class AccountManagementService
public async Task<Account?> GetAccountAsync(int id)
{
return await _accountRepository.GetByIdAsync(id);
var account = await _accountRepository.GetByIdAsync(id);
FormatPhoneForDisplay(account);
return account;
}
public async Task<Account?> GetAccountByPhoneAsync(string phone)
{
return await _accountRepository.GetByPhoneAsync(phone);
var digits = PhoneNumberFormatter.NormalizeToDigits(phone);
var account = await _accountRepository.GetByPhoneAsync(digits);
FormatPhoneForDisplay(account);
return account;
}
public async Task<IEnumerable<Account>> GetAllAccountsAsync()
{
return await _accountRepository.GetAllAsync();
var list = (await _accountRepository.GetAllAsync()).ToList();
foreach (var a in list)
FormatPhoneForDisplay(a);
return list;
}
public async Task<IEnumerable<Account>> GetActiveAccountsAsync()
{
return await _accountRepository.GetActiveAccountsAsync();
var list = (await _accountRepository.GetActiveAccountsAsync()).ToList();
foreach (var a in list)
FormatPhoneForDisplay(a);
return list;
}
public async Task<IEnumerable<Account>> GetAccountsByCategoryAsync(int categoryId)
{
return await _accountRepository.GetByCategoryAsync(categoryId);
var list = (await _accountRepository.GetByCategoryAsync(categoryId)).ToList();
foreach (var a in list)
FormatPhoneForDisplay(a);
return list;
}
public async Task<Account> CreateAccountAsync(Account account)
{
account.Phone = PhoneNumberFormatter.NormalizeToDigits(account.Phone);
return await _accountRepository.AddAsync(account);
}
public async Task UpdateAccountAsync(Account account)
{
account.Phone = PhoneNumberFormatter.NormalizeToDigits(account.Phone);
await _accountRepository.UpdateAsync(account);
}
@@ -212,6 +229,14 @@ public class AccountManagementService
return count == 0 ? string.Empty : new string(digits, 0, count);
}
private static void FormatPhoneForDisplay(Account? account)
{
if (account == null)
return;
account.Phone = PhoneNumberFormatter.FormatWithCountryCode(account.Phone);
}
private static string? TryFindRepoRoot()
{
var current = Directory.GetCurrentDirectory();
@@ -3,6 +3,7 @@ using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using TelegramPanel.Core.Interfaces;
using TelegramPanel.Core.Services;
using TelegramPanel.Core.Utils;
using TelegramPanel.Data.Entities;
using System.IO.Compression;
using WTelegram;
@@ -63,7 +64,10 @@ public class AccountImportService
try
{
// 入库策略:按手机号 upsert(方便重复导入/替换 session)
var phone = result.Phone!;
var phone = PhoneNumberFormatter.NormalizeToDigits(result.Phone);
if (string.IsNullOrWhiteSpace(phone))
throw new InvalidOperationException("导入结果缺少有效手机号");
var existing = await _accountManagement.GetAccountByPhoneAsync(phone);
if (existing != null)
{
@@ -156,7 +160,10 @@ public class AccountImportService
{
try
{
var phone = result.Phone!;
var phone = PhoneNumberFormatter.NormalizeToDigits(result.Phone);
if (string.IsNullOrWhiteSpace(phone))
throw new InvalidOperationException("导入结果缺少有效手机号");
var existing = await _accountManagement.GetAccountByPhoneAsync(phone);
if (existing != null)
{
@@ -341,7 +348,9 @@ public class AccountImportService
if (!TryGetString(root, out var phone, "phone", "phone_number", "phoneNumber") || string.IsNullOrWhiteSpace(phone))
return new ImportResult(false, null, null, null, null, $"json 缺少 phone: {jsonPath}");
phone = phone.Trim();
phone = PhoneNumberFormatter.NormalizeToDigits(phone);
if (string.IsNullOrWhiteSpace(phone))
return new ImportResult(false, null, null, null, null, $"json phone 无效: {jsonPath}");
_ = TryGetLong(root, out var userId, "user_id", "uid", "userId");
_ = TryGetString(root, out var username, "username");
@@ -8,6 +8,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="libphonenumber-csharp" Version="9.0.21" />
<PackageReference Include="WTelegramClient" Version="4.*" />
<PackageReference Include="SixLabors.ImageSharp" Version="3.*" />
<PackageReference Include="Microsoft.Data.Sqlite" Version="8.*" />
@@ -0,0 +1,56 @@
using PhoneNumbers;
namespace TelegramPanel.Core.Utils;
/// <summary>
/// 手机号格式化/规范化工具(用于展示国家码)
/// </summary>
public static class PhoneNumberFormatter
{
private static readonly PhoneNumberUtil Util = PhoneNumberUtil.GetInstance();
/// <summary>
/// 仅保留数字(用于数据库存储/查询/文件名)
/// </summary>
public static string NormalizeToDigits(string? phone)
{
if (string.IsNullOrWhiteSpace(phone))
return string.Empty;
var digits = new char[phone.Length];
var count = 0;
foreach (var ch in phone)
{
if (ch >= '0' && ch <= '9')
digits[count++] = ch;
}
return count == 0 ? string.Empty : new string(digits, 0, count);
}
/// <summary>
/// 格式化为 “+国家码 空格 本地号码” 的展示形式,如:+86 13800138000
/// </summary>
public static string FormatWithCountryCode(string? phone)
{
var digits = NormalizeToDigits(phone);
if (digits.Length == 0)
return (phone ?? string.Empty).Trim();
try
{
// Telegram 账号手机号通常是 E.164 数字串(无 +),这里统一按 E.164 解析
var number = Util.Parse("+" + digits, defaultRegion: null);
var nsn = Util.GetNationalSignificantNumber(number);
if (string.IsNullOrWhiteSpace(nsn))
return "+" + digits;
return $"+{number.CountryCode} {nsn}";
}
catch
{
// 解析失败也至少补上 "+"
return "+" + digits;
}
}
}
@@ -342,8 +342,15 @@
{
try
{
var phoneDigits = TelegramPanel.Core.Utils.PhoneNumberFormatter.NormalizeToDigits(accountInfo.Phone);
if (string.IsNullOrWhiteSpace(phoneDigits))
{
Snackbar.Add("手机号无效,无法保存账号", Severity.Error);
return;
}
// 检查账号是否已存在
var existingAccount = await AccountManagement.GetAccountByPhoneAsync(accountInfo.Phone!);
var existingAccount = await AccountManagement.GetAccountByPhoneAsync(phoneDigits);
if (existingAccount != null)
{
@@ -364,11 +371,11 @@
// 创建新账号
var account = new Account
{
Phone = accountInfo.Phone!,
Phone = phoneDigits,
UserId = accountInfo.TelegramUserId,
Nickname = BuildNickname(accountInfo),
Username = accountInfo.Username,
SessionPath = System.IO.Path.Combine(sessionsPath, $"{accountInfo.Phone}.session"),
SessionPath = System.IO.Path.Combine(sessionsPath, $"{phoneDigits}.session"),
ApiId = telegramApiId,
ApiHash = telegramApiHash,
IsActive = true,