("版本信息", new DialogParameters(), options);
+ await Task.CompletedTask;
+ }
}
diff --git a/src/TelegramPanel.Web/Components/Pages/AccountImport.razor b/src/TelegramPanel.Web/Components/Pages/AccountImport.razor
index bffd662..7082651 100644
--- a/src/TelegramPanel.Web/Components/Pages/AccountImport.razor
+++ b/src/TelegramPanel.Web/Components/Pages/AccountImport.razor
@@ -20,12 +20,14 @@
- 单账号:Zip 根目录直接包含一个 .json + 一个 .session
- 批量导入:每个账号一个独立子文件夹,文件夹内包含一个 .json + 一个 .session
+ - 二级密码:自动解析账号目录下的 2fa.txt 文件作为二级密码保存到数据库
批量结构示例:
xx.zip
├─ 8613111111111
│ ├─ 8613111111111.json
- │ └─ 8613111111111.session
+ │ ├─ 8613111111111.session
+ │ └─ 2fa.txt (可选,内容为二级密码)
└─ 8615119714541
├─ 8615119714541.json
└─ 8615119714541.session
@@ -45,6 +47,10 @@
已选择:@zipFile.Name(@zipFile.Size bytes)
}
+
+
@@ -168,6 +174,7 @@
private IBrowserFile? zipFile;
private bool importingZip = false;
+ private string zipTwoFactorPassword = "";
private string sessionString = "";
private bool importingString = false;
@@ -205,7 +212,8 @@
try
{
- var results = await AccountImportService.ImportFromZipAsync(zipFile);
+ var twoFactorPwd = string.IsNullOrWhiteSpace(zipTwoFactorPassword) ? null : zipTwoFactorPassword.Trim();
+ var results = await AccountImportService.ImportFromZipAsync(zipFile, twoFactorPassword: twoFactorPwd);
importResults.AddRange(results);
var successCount = results.Count(r => r.Success);
@@ -217,6 +225,7 @@
Snackbar.Add($"{failureCount} 个账号导入失败", Severity.Warning);
zipFile = null;
+ zipTwoFactorPassword = "";
}
catch (Exception ex)
{
diff --git a/src/TelegramPanel.Web/Components/Pages/Accounts.razor b/src/TelegramPanel.Web/Components/Pages/Accounts.razor
index b882ced..5ca7d7f 100644
--- a/src/TelegramPanel.Web/Components/Pages/Accounts.razor
+++ b/src/TelegramPanel.Web/Components/Pages/Accounts.razor
@@ -88,7 +88,7 @@
操作
- @context.Phone
+ @context.DisplayPhone
@(context.Nickname ?? "-")
@(context.Username ?? "-")
@context.UserId
@@ -248,11 +248,15 @@
private async Task ShowDetails(Account account)
{
- var (channels, groups) = await AccountManagement.GetAccountStatisticsAsync(account.Id);
- var createdAt = TimeZone.Format(account.CreatedAt, "yyyy-MM-dd HH:mm");
- var lastSyncAt = TimeZone.Format(account.LastSyncAt, "yyyy-MM-dd HH:mm");
- var message = $"账号详情:\n手机号:{account.Phone}\n用户名:{account.Username ?? "无"}\n用户ID:{account.UserId}\n分类:{account.Category?.Name ?? "未分类"}\n创建的频道:{channels} 个\n创建的群组:{groups} 个\n创建时间:{createdAt}\n最后数据同步:{lastSyncAt}\nSession路径:{account.SessionPath}";
- await DialogService.ShowMessageBox("账号详情", message, "关闭");
+ var parameters = new DialogParameters
+ {
+ ["AccountId"] = account.Id
+ };
+ var options = new DialogOptions { CloseOnEscapeKey = true, MaxWidth = MaxWidth.Small, FullWidth = true };
+ var dialog = DialogService.Show("账号详情", parameters, options)!;
+ var result = await dialog.Result;
+ if (result is { Canceled: false })
+ await LoadAccounts();
}
private async Task OpenChangeTwoFactorPassword(Account account)
@@ -569,7 +573,7 @@
// 资料刷新后重新加载(昵称/用户名/用户ID 可能更新)
await LoadAccounts();
- Snackbar.Add($"账号 {account.Phone} 状态:{result.Summary}", result.Ok ? Severity.Success : Severity.Warning);
+ Snackbar.Add($"账号 {account.DisplayPhone} 状态:{result.Summary}", result.Ok ? Severity.Success : Severity.Warning);
}
catch (Exception ex)
{
@@ -857,7 +861,7 @@
var parameters = new DialogParameters
{
["AccountId"] = account.Id,
- ["Phone"] = account.Phone
+ ["Phone"] = account.DisplayPhone
};
var options = new DialogOptions { CloseOnEscapeKey = true, MaxWidth = MaxWidth.Medium, FullWidth = true };
@@ -870,7 +874,7 @@
var parameters = new DialogParameters
{
["AccountId"] = account.Id,
- ["Phone"] = account.Phone
+ ["Phone"] = account.DisplayPhone
};
var options = new DialogOptions { CloseOnEscapeKey = true, MaxWidth = MaxWidth.Large, FullWidth = true };
@@ -900,7 +904,7 @@
{
bool? result = await DialogService.ShowMessageBox(
"确认删除",
- $"确定要删除账号 {account.Phone} 吗?此操作不可撤销!",
+ $"确定要删除账号 {account.DisplayPhone} 吗?此操作不可撤销!",
yesText: "删除", cancelText: "取消");
if (result == true)
diff --git a/src/TelegramPanel.Web/Components/Pages/Channels.razor b/src/TelegramPanel.Web/Components/Pages/Channels.razor
index a64343a..cac0acf 100644
--- a/src/TelegramPanel.Web/Components/Pages/Channels.razor
+++ b/src/TelegramPanel.Web/Components/Pages/Channels.razor
@@ -115,7 +115,7 @@
@if (context.CreatorAccount != null)
{
- @context.CreatorAccount.Phone
+ @context.CreatorAccount.DisplayPhone
}
else if (context.CreatorAccountId != null)
{
diff --git a/src/TelegramPanel.Web/Components/Pages/Groups.razor b/src/TelegramPanel.Web/Components/Pages/Groups.razor
index 13a77ce..d654bb6 100644
--- a/src/TelegramPanel.Web/Components/Pages/Groups.razor
+++ b/src/TelegramPanel.Web/Components/Pages/Groups.razor
@@ -23,7 +23,7 @@
全部账号
@foreach (var account in accounts)
{
- @account.Phone (@account.Username)
+ @account.DisplayPhone (@account.Username)
}
@if (context.CreatorAccount != null)
{
- @context.CreatorAccount.Phone
+ @context.CreatorAccount.DisplayPhone
}
else
{
diff --git a/src/TelegramPanel.Web/Services/VersionService.cs b/src/TelegramPanel.Web/Services/VersionService.cs
new file mode 100644
index 0000000..e107170
--- /dev/null
+++ b/src/TelegramPanel.Web/Services/VersionService.cs
@@ -0,0 +1,58 @@
+using System.Reflection;
+
+namespace TelegramPanel.Web.Services;
+
+///
+/// 版本信息服务(静态类),用于获取应用程序版本号
+///
+public static class VersionService
+{
+ private static readonly Lazy _version = new(GetVersionFromAssembly);
+ private static readonly Lazy _fullVersion = new(GetFullVersionFromAssembly);
+
+ ///
+ /// 获取简化版本号(如:1.0.0)
+ ///
+ public static string Version => _version.Value;
+
+ ///
+ /// 获取完整版本信息(包含 InformationalVersion,如:1.0.0+commitHash)
+ ///
+ public static string FullVersion => _fullVersion.Value;
+
+ private static string GetVersionFromAssembly()
+ {
+ var assembly = Assembly.GetEntryAssembly() ?? Assembly.GetExecutingAssembly();
+
+ // 优先使用 InformationalVersion(更友好的版本号)
+ var infoVersion = assembly
+ .GetCustomAttribute()?
+ .InformationalVersion;
+
+ if (!string.IsNullOrWhiteSpace(infoVersion))
+ {
+ // 移除可能的 +commitHash 后缀,只保留版本号部分
+ var plusIndex = infoVersion.IndexOf('+');
+ return plusIndex > 0 ? infoVersion[..plusIndex] : infoVersion;
+ }
+
+ // 回退到 AssemblyVersion
+ var version = assembly.GetName().Version;
+ return version != null
+ ? $"{version.Major}.{version.Minor}.{version.Build}"
+ : "Unknown";
+ }
+
+ private static string GetFullVersionFromAssembly()
+ {
+ var assembly = Assembly.GetEntryAssembly() ?? Assembly.GetExecutingAssembly();
+
+ var infoVersion = assembly
+ .GetCustomAttribute()?
+ .InformationalVersion;
+
+ return !string.IsNullOrWhiteSpace(infoVersion)
+ ? infoVersion
+ : GetVersionFromAssembly();
+ }
+}