diff --git a/src/TelegramPanel.Core/Services/AccountRiskService.cs b/src/TelegramPanel.Core/Services/AccountRiskService.cs
index 95774ee..01e8074 100644
--- a/src/TelegramPanel.Core/Services/AccountRiskService.cs
+++ b/src/TelegramPanel.Core/Services/AccountRiskService.cs
@@ -17,9 +17,12 @@ public class AccountRiskService
///
public RiskCheckResult CheckLoginDuration(Account account)
{
- if (account.LastLoginAt == null)
+ var referenceAt = account.GetRiskReferenceAtUtc();
+ var loginHours = account.GetRiskReferenceHours();
+
+ if (referenceAt == null || loginHours == null)
{
- // 无登录记录,视为高风险(刚导入的账号)
+ // 兜底:完全缺少可参考的时间,视为高风险
return new RiskCheckResult
{
IsRisky = true,
@@ -28,16 +31,30 @@ public class AccountRiskService
};
}
- var loginHours = (DateTime.UtcNow - account.LastLoginAt.Value).TotalHours;
-
- if (loginHours < RISK_THRESHOLD_HOURS)
+ // 兼容历史数据:LastLoginAt 为空时,使用导入时间(CreatedAt)作为估算,避免永久误报
+ var isEstimated = account.IsRiskReferenceEstimated();
+ if (isEstimated && loginHours >= RISK_THRESHOLD_HOURS)
{
- var remainingHours = RISK_THRESHOLD_HOURS - loginHours;
+ return new RiskCheckResult
+ {
+ IsRisky = false,
+ Message = "账号登录时长已满足要求(按导入时间估算)",
+ DetailedMessage = $"当前已导入时长:{loginHours.Value:F1} 小时"
+ };
+ }
+
+ if (loginHours.Value < RISK_THRESHOLD_HOURS)
+ {
+ var remainingHours = RISK_THRESHOLD_HOURS - loginHours.Value;
return new RiskCheckResult
{
IsRisky = true,
- Message = $"账号登录时长不足 24 小时(当前:{loginHours:F1} 小时)",
- DetailedMessage = $"建议等待 {remainingHours:F1} 小时后再进行敏感操作,以降低被 Telegram 风控的风险"
+ Message = isEstimated
+ ? $"账号未记录登录时间(按导入时间估算:{loginHours.Value:F1} 小时)"
+ : $"账号登录时长不足 24 小时(当前:{loginHours.Value:F1} 小时)",
+ DetailedMessage = isEstimated
+ ? $"该账号尚未记录登录时间(可能是较早导入的账号),已按导入时间估算;建议等待 {remainingHours:F1} 小时后再进行敏感操作,以降低被 Telegram 风控的风险"
+ : $"建议等待 {remainingHours:F1} 小时后再进行敏感操作,以降低被 Telegram 风控的风险"
};
}
@@ -45,7 +62,7 @@ public class AccountRiskService
{
IsRisky = false,
Message = "账号登录时长已满足要求",
- DetailedMessage = $"当前登录时长:{loginHours:F1} 小时"
+ DetailedMessage = $"当前登录时长:{loginHours.Value:F1} 小时"
};
}
@@ -145,8 +162,12 @@ public class BatchRiskCheckResult
var riskyPhones = string.Join("、", RiskyAccounts.Select(a =>
{
- var hours = a.GetLoginHours();
- return hours.HasValue ? $"{a.Phone}({hours.Value:F1}h)" : a.Phone;
+ var hours = a.GetRiskReferenceHours();
+ if (!hours.HasValue)
+ return a.Phone;
+
+ var tag = a.IsRiskReferenceEstimated() ? "导入" : "登录";
+ return $"{a.Phone}({tag}{hours.Value:F1}h)";
}));
return $"以下账号登录时长不足 24 小时:{riskyPhones}";
diff --git a/src/TelegramPanel.Data/Entities/AccountExtensions.cs b/src/TelegramPanel.Data/Entities/AccountExtensions.cs
index 8785fca..f2efc28 100644
--- a/src/TelegramPanel.Data/Entities/AccountExtensions.cs
+++ b/src/TelegramPanel.Data/Entities/AccountExtensions.cs
@@ -5,6 +5,42 @@ namespace TelegramPanel.Data.Entities;
///
public static class AccountExtensions
{
+ ///
+ /// 获取风控检查用的参考时间(优先 LastLoginAt,其次 CreatedAt/LastSyncAt 作为估算兜底)
+ ///
+ public static DateTime? GetRiskReferenceAtUtc(this Account account)
+ {
+ if (account.LastLoginAt != null)
+ return account.LastLoginAt.Value;
+
+ // 兼容历史数据:早期导入的账号可能没有写入 LastLoginAt
+ if (account.CreatedAt != default)
+ return account.CreatedAt;
+
+ if (account.LastSyncAt != default)
+ return account.LastSyncAt;
+
+ return null;
+ }
+
+ ///
+ /// 风控参考时间是否为估算值(非真实登录时间)
+ ///
+ public static bool IsRiskReferenceEstimated(this Account account)
+ => account.LastLoginAt == null && account.GetRiskReferenceAtUtc() != null;
+
+ ///
+ /// 获取风控检查用的参考小时数
+ ///
+ public static double? GetRiskReferenceHours(this Account account)
+ {
+ var at = account.GetRiskReferenceAtUtc();
+ if (at == null)
+ return null;
+
+ return (DateTime.UtcNow - at.Value).TotalHours;
+ }
+
///
/// 获取登录小时数的格式化字符串
///
diff --git a/src/TelegramPanel.Web/Components/Pages/AccountLogin.razor b/src/TelegramPanel.Web/Components/Pages/AccountLogin.razor
index 0a7d086..86cdd7a 100644
--- a/src/TelegramPanel.Web/Components/Pages/AccountLogin.razor
+++ b/src/TelegramPanel.Web/Components/Pages/AccountLogin.razor
@@ -354,6 +354,7 @@
existingAccount.ApiId = telegramApiId;
existingAccount.ApiHash = telegramApiHash;
existingAccount.LastSyncAt = DateTime.UtcNow;
+ existingAccount.LastLoginAt = DateTime.UtcNow;
await AccountManagement.UpdateAccountAsync(existingAccount);
Snackbar.Add("账号信息已更新", Severity.Success);
@@ -372,7 +373,8 @@
ApiHash = telegramApiHash,
IsActive = true,
CreatedAt = DateTime.UtcNow,
- LastSyncAt = DateTime.UtcNow
+ LastSyncAt = DateTime.UtcNow,
+ LastLoginAt = DateTime.UtcNow
};
await AccountManagement.CreateAccountAsync(account);