From a71417cb324f8910877be73145d574b7535dfaa9 Mon Sep 17 00:00:00 2001 From: meoacgx Date: Wed, 24 Dec 2025 02:20:16 +0800 Subject: [PATCH] =?UTF-8?q?=E6=89=8B=E6=9C=BA=E5=8F=B7=E6=98=BE=E7=A4=BA?= =?UTF-8?q?=E8=A1=A5=E5=85=A8=E5=9B=BD=E5=AE=B6=E7=A0=81=E6=A0=BC=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Services/AccountManagementService.cs | 35 ++++++++++-- .../Services/Telegram/AccountImportService.cs | 15 ++++- .../TelegramPanel.Core.csproj | 1 + .../Utils/PhoneNumberFormatter.cs | 56 +++++++++++++++++++ .../Components/Pages/AccountLogin.razor | 13 ++++- 5 files changed, 109 insertions(+), 11 deletions(-) create mode 100644 src/TelegramPanel.Core/Utils/PhoneNumberFormatter.cs diff --git a/src/TelegramPanel.Core/Services/AccountManagementService.cs b/src/TelegramPanel.Core/Services/AccountManagementService.cs index 4bb0cdd..f72c287 100644 --- a/src/TelegramPanel.Core/Services/AccountManagementService.cs +++ b/src/TelegramPanel.Core/Services/AccountManagementService.cs @@ -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 GetAccountAsync(int id) { - return await _accountRepository.GetByIdAsync(id); + var account = await _accountRepository.GetByIdAsync(id); + FormatPhoneForDisplay(account); + return account; } public async Task 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> GetAllAccountsAsync() { - return await _accountRepository.GetAllAsync(); + var list = (await _accountRepository.GetAllAsync()).ToList(); + foreach (var a in list) + FormatPhoneForDisplay(a); + return list; } public async Task> GetActiveAccountsAsync() { - return await _accountRepository.GetActiveAccountsAsync(); + var list = (await _accountRepository.GetActiveAccountsAsync()).ToList(); + foreach (var a in list) + FormatPhoneForDisplay(a); + return list; } public async Task> 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 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(); diff --git a/src/TelegramPanel.Core/Services/Telegram/AccountImportService.cs b/src/TelegramPanel.Core/Services/Telegram/AccountImportService.cs index e02c486..49032f2 100644 --- a/src/TelegramPanel.Core/Services/Telegram/AccountImportService.cs +++ b/src/TelegramPanel.Core/Services/Telegram/AccountImportService.cs @@ -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"); diff --git a/src/TelegramPanel.Core/TelegramPanel.Core.csproj b/src/TelegramPanel.Core/TelegramPanel.Core.csproj index e527100..6d358a6 100644 --- a/src/TelegramPanel.Core/TelegramPanel.Core.csproj +++ b/src/TelegramPanel.Core/TelegramPanel.Core.csproj @@ -8,6 +8,7 @@ + diff --git a/src/TelegramPanel.Core/Utils/PhoneNumberFormatter.cs b/src/TelegramPanel.Core/Utils/PhoneNumberFormatter.cs new file mode 100644 index 0000000..cb22a13 --- /dev/null +++ b/src/TelegramPanel.Core/Utils/PhoneNumberFormatter.cs @@ -0,0 +1,56 @@ +using PhoneNumbers; + +namespace TelegramPanel.Core.Utils; + +/// +/// 手机号格式化/规范化工具(用于展示国家码) +/// +public static class PhoneNumberFormatter +{ + private static readonly PhoneNumberUtil Util = PhoneNumberUtil.GetInstance(); + + /// + /// 仅保留数字(用于数据库存储/查询/文件名) + /// + 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); + } + + /// + /// 格式化为 “+国家码 空格 本地号码” 的展示形式,如:+86 13800138000 + /// + 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; + } + } +} diff --git a/src/TelegramPanel.Web/Components/Pages/AccountLogin.razor b/src/TelegramPanel.Web/Components/Pages/AccountLogin.razor index 86cdd7a..95d374c 100644 --- a/src/TelegramPanel.Web/Components/Pages/AccountLogin.razor +++ b/src/TelegramPanel.Web/Components/Pages/AccountLogin.razor @@ -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,