From ccb3f3e8a2d4778fa427e33844a173aea06c02f8 Mon Sep 17 00:00:00 2001 From: meoacgx Date: Sat, 20 Dec 2025 21:23:28 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=9E=E7=8E=B0=E8=B4=A6=E5=8F=B7=E9=A3=8E?= =?UTF-8?q?=E6=8E=A7=E7=B3=BB=E7=BB=9F=EF=BC=9A24=E5=B0=8F=E6=97=B6?= =?UTF-8?q?=E7=99=BB=E5=BD=95=E6=97=B6=E9=95=BF=E6=A3=80=E6=9F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 核心功能: - 新增 AccountRiskService 风控检查服务 - 添加 Account.LastLoginAt 字段记录登录时间 - 实现 24 小时风控阈值检查逻辑 - 新增 RiskWarningDialog 风控警告对话框 风控集成点: - 创建频道(ChannelCreate) - 深度探测账号状态(Accounts - 深度探测) - 批量修改昵称(BatchChangeNicknameDialog) - 批量修改个性签名(BatchChangeBioDialog) - 编辑用户资料(EditUserProfileDialog) 风控逻辑: - 刚导入账号(LastLoginAt 为 null)→ 高风险 - 登录时长 < 24 小时 → 高风险,提示剩余等待时间 - 登录时长 ≥ 24 小时 → 安全,允许操作 数据库变更: - 添加 Accounts.LastLoginAt (nullable DateTime) 字段 - 创建数据库迁移 20251220000000_AddLastLoginAt 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- .../ServiceCollectionExtensions.cs | 3 + .../Services/AccountRiskService.cs | 154 ++++++++++++++++++ .../Services/RiskWarningAction.cs | 17 ++ src/TelegramPanel.Data/Entities/Account.cs | 5 + .../Entities/AccountExtensions.cs | 30 ++++ .../20251220000000_AddLastLoginAt.cs | 32 ++++ .../Migrations/AppDbContextModelSnapshot.cs | 19 +++ .../Dialogs/BatchChangeBioDialog.razor | 33 ++++ .../Dialogs/BatchChangeNicknameDialog.razor | 33 ++++ .../Dialogs/EditUserProfileDialog.razor | 21 +++ .../Dialogs/RiskWarningDialog.razor | 110 +++++++++++++ .../Components/Pages/Accounts.razor | 71 +++++++- .../Components/Pages/ChannelCreate.razor | 24 +++ 13 files changed, 550 insertions(+), 2 deletions(-) create mode 100644 src/TelegramPanel.Core/Services/AccountRiskService.cs create mode 100644 src/TelegramPanel.Core/Services/RiskWarningAction.cs create mode 100644 src/TelegramPanel.Data/Entities/AccountExtensions.cs create mode 100644 src/TelegramPanel.Data/Migrations/20251220000000_AddLastLoginAt.cs create mode 100644 src/TelegramPanel.Web/Components/Dialogs/RiskWarningDialog.razor diff --git a/src/TelegramPanel.Core/ServiceCollectionExtensions.cs b/src/TelegramPanel.Core/ServiceCollectionExtensions.cs index 1597170..dea1c0c 100644 --- a/src/TelegramPanel.Core/ServiceCollectionExtensions.cs +++ b/src/TelegramPanel.Core/ServiceCollectionExtensions.cs @@ -35,6 +35,9 @@ public static class ServiceCollectionExtensions services.AddScoped(); services.AddScoped(); + // 注册风控服务 + services.AddScoped(); + return services; } } diff --git a/src/TelegramPanel.Core/Services/AccountRiskService.cs b/src/TelegramPanel.Core/Services/AccountRiskService.cs new file mode 100644 index 0000000..95774ee --- /dev/null +++ b/src/TelegramPanel.Core/Services/AccountRiskService.cs @@ -0,0 +1,154 @@ +using TelegramPanel.Data.Entities; + +namespace TelegramPanel.Core.Services; + +/// +/// 账号风控检查服务 +/// +public class AccountRiskService +{ + /// + /// 风控阈值:登录后需满 24 小时才能进行敏感操作 + /// + private const double RISK_THRESHOLD_HOURS = 24.0; + + /// + /// 检查单个账号的登录时长是否满足风控要求 + /// + public RiskCheckResult CheckLoginDuration(Account account) + { + if (account.LastLoginAt == null) + { + // 无登录记录,视为高风险(刚导入的账号) + return new RiskCheckResult + { + IsRisky = true, + Message = "账号未记录登录时间", + DetailedMessage = "该账号尚未记录登录时间(可能是刚导入的新账号),建议等待 24 小时后再进行敏感操作" + }; + } + + var loginHours = (DateTime.UtcNow - account.LastLoginAt.Value).TotalHours; + + if (loginHours < RISK_THRESHOLD_HOURS) + { + var remainingHours = RISK_THRESHOLD_HOURS - loginHours; + return new RiskCheckResult + { + IsRisky = true, + Message = $"账号登录时长不足 24 小时(当前:{loginHours:F1} 小时)", + DetailedMessage = $"建议等待 {remainingHours:F1} 小时后再进行敏感操作,以降低被 Telegram 风控的风险" + }; + } + + return new RiskCheckResult + { + IsRisky = false, + Message = "账号登录时长已满足要求", + DetailedMessage = $"当前登录时长:{loginHours:F1} 小时" + }; + } + + /// + /// 批量检查账号的登录时长 + /// + public BatchRiskCheckResult CheckBatchAccounts(IEnumerable accounts) + { + var accountList = accounts.ToList(); + var riskyAccounts = new List(); + var safeAccounts = new List(); + + foreach (var account in accountList) + { + var check = CheckLoginDuration(account); + if (check.IsRisky) + riskyAccounts.Add(account); + else + safeAccounts.Add(account); + } + + return new BatchRiskCheckResult + { + TotalCount = accountList.Count, + RiskyCount = riskyAccounts.Count, + SafeCount = safeAccounts.Count, + RiskyAccounts = riskyAccounts, + SafeAccounts = safeAccounts, + HasRiskyAccounts = riskyAccounts.Count > 0 + }; + } +} + +/// +/// 单账号风控检查结果 +/// +public class RiskCheckResult +{ + /// + /// 是否存在风险 + /// + public bool IsRisky { get; set; } + + /// + /// 风险消息 + /// + public string Message { get; set; } = string.Empty; + + /// + /// 详细说明 + /// + public string DetailedMessage { get; set; } = string.Empty; +} + +/// +/// 批量账号风控检查结果 +/// +public class BatchRiskCheckResult +{ + /// + /// 总账号数 + /// + public int TotalCount { get; set; } + + /// + /// 风险账号数 + /// + public int RiskyCount { get; set; } + + /// + /// 安全账号数 + /// + public int SafeCount { get; set; } + + /// + /// 风险账号列表 + /// + public List RiskyAccounts { get; set; } = new(); + + /// + /// 安全账号列表 + /// + public List SafeAccounts { get; set; } = new(); + + /// + /// 是否存在风险账号 + /// + public bool HasRiskyAccounts { get; set; } + + /// + /// 获取风险摘要信息 + /// + public string GetRiskySummary() + { + if (RiskyCount == 0) + return "所有账号均已满足登录时长要求"; + + var riskyPhones = string.Join("、", RiskyAccounts.Select(a => + { + var hours = a.GetLoginHours(); + return hours.HasValue ? $"{a.Phone}({hours.Value:F1}h)" : a.Phone; + })); + + return $"以下账号登录时长不足 24 小时:{riskyPhones}"; + } +} diff --git a/src/TelegramPanel.Core/Services/RiskWarningAction.cs b/src/TelegramPanel.Core/Services/RiskWarningAction.cs new file mode 100644 index 0000000..7102558 --- /dev/null +++ b/src/TelegramPanel.Core/Services/RiskWarningAction.cs @@ -0,0 +1,17 @@ +namespace TelegramPanel.Core.Services; + +/// +/// 风控警告对话框的用户操作 +/// +public enum RiskWarningAction +{ + /// + /// 继续操作(包含风险账号) + /// + Continue, + + /// + /// 排除风险账号后继续 + /// + ExcludeRisky +} diff --git a/src/TelegramPanel.Data/Entities/Account.cs b/src/TelegramPanel.Data/Entities/Account.cs index 1aa54eb..bbc2043 100644 --- a/src/TelegramPanel.Data/Entities/Account.cs +++ b/src/TelegramPanel.Data/Entities/Account.cs @@ -21,6 +21,11 @@ public class Account public DateTime CreatedAt { get; set; } = DateTime.UtcNow; public DateTime LastSyncAt { get; set; } = DateTime.UtcNow; + /// + /// 最后一次登录 Telegram 的时间(UTC),用于风控检查 + /// + public DateTime? LastLoginAt { get; set; } + /// /// Telegram 状态检测结果摘要(用于页面刷新后仍可展示上次检测结论) /// diff --git a/src/TelegramPanel.Data/Entities/AccountExtensions.cs b/src/TelegramPanel.Data/Entities/AccountExtensions.cs new file mode 100644 index 0000000..8785fca --- /dev/null +++ b/src/TelegramPanel.Data/Entities/AccountExtensions.cs @@ -0,0 +1,30 @@ +namespace TelegramPanel.Data.Entities; + +/// +/// Account 实体扩展方法 +/// +public static class AccountExtensions +{ + /// + /// 获取登录小时数的格式化字符串 + /// + public static string GetLoginHoursFormatted(this Account account) + { + if (account.LastLoginAt == null) + return "未知"; + + var hours = (DateTime.UtcNow - account.LastLoginAt.Value).TotalHours; + return hours.ToString("F1"); + } + + /// + /// 获取登录小时数 + /// + public static double? GetLoginHours(this Account account) + { + if (account.LastLoginAt == null) + return null; + + return (DateTime.UtcNow - account.LastLoginAt.Value).TotalHours; + } +} diff --git a/src/TelegramPanel.Data/Migrations/20251220000000_AddLastLoginAt.cs b/src/TelegramPanel.Data/Migrations/20251220000000_AddLastLoginAt.cs new file mode 100644 index 0000000..3429d37 --- /dev/null +++ b/src/TelegramPanel.Data/Migrations/20251220000000_AddLastLoginAt.cs @@ -0,0 +1,32 @@ +using System; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace TelegramPanel.Data.Migrations +{ + [DbContext(typeof(AppDbContext))] + [Migration("20251220000000_AddLastLoginAt")] + /// + public partial class AddLastLoginAt : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "LastLoginAt", + table: "Accounts", + type: "TEXT", + nullable: true); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "LastLoginAt", + table: "Accounts"); + } + } +} diff --git a/src/TelegramPanel.Data/Migrations/AppDbContextModelSnapshot.cs b/src/TelegramPanel.Data/Migrations/AppDbContextModelSnapshot.cs index 820fe61..f24afea 100644 --- a/src/TelegramPanel.Data/Migrations/AppDbContextModelSnapshot.cs +++ b/src/TelegramPanel.Data/Migrations/AppDbContextModelSnapshot.cs @@ -40,9 +40,16 @@ namespace TelegramPanel.Data.Migrations b.Property("IsActive") .HasColumnType("INTEGER"); + b.Property("LastLoginAt") + .HasColumnType("TEXT"); + b.Property("LastSyncAt") .HasColumnType("TEXT"); + b.Property("Nickname") + .HasMaxLength(100) + .HasColumnType("TEXT"); + b.Property("Phone") .IsRequired() .HasMaxLength(20) @@ -53,6 +60,18 @@ namespace TelegramPanel.Data.Migrations .HasMaxLength(500) .HasColumnType("TEXT"); + b.Property("TelegramStatusCheckedAtUtc") + .HasColumnType("TEXT"); + + b.Property("TelegramStatusDetails") + .HasColumnType("TEXT"); + + b.Property("TelegramStatusOk") + .HasColumnType("INTEGER"); + + b.Property("TelegramStatusSummary") + .HasColumnType("TEXT"); + b.Property("UserId") .HasColumnType("INTEGER"); diff --git a/src/TelegramPanel.Web/Components/Dialogs/BatchChangeBioDialog.razor b/src/TelegramPanel.Web/Components/Dialogs/BatchChangeBioDialog.razor index 8f5ff19..03e9099 100644 --- a/src/TelegramPanel.Web/Components/Dialogs/BatchChangeBioDialog.razor +++ b/src/TelegramPanel.Web/Components/Dialogs/BatchChangeBioDialog.razor @@ -1,6 +1,7 @@ @namespace TelegramPanel.Web.Components.Dialogs @inject AccountManagementService AccountManagement @inject TelegramPanel.Core.Services.Telegram.AccountTelegramToolsService AccountTelegramTools +@inject TelegramPanel.Core.Services.AccountRiskService RiskService @inject ISnackbar Snackbar @inject IDialogService DialogService @using TelegramPanel.Data.Entities @@ -101,6 +102,38 @@ return; } + // 批量风控检查:修改 Bio 是敏感操作 + var batchCheck = RiskService.CheckBatchAccounts(accounts); + if (batchCheck.HasRiskyAccounts) + { + var parameters = new DialogParameters + { + ["Message"] = $"检测到 {batchCheck.RiskyCount} 个风险账号", + ["DetailedMessage"] = batchCheck.GetRiskySummary(), + ["ShowRecommendations"] = true, + ["ShowExcludeOption"] = true, + ["RiskyAccounts"] = batchCheck.RiskyAccounts.ToList() + }; + var options = new DialogOptions { CloseOnEscapeKey = true, MaxWidth = MaxWidth.Large }; + var dialog = DialogService.Show("批量操作风控警告", parameters, options); + var result = await dialog.Result; + + if (result.Canceled) + return; // 用户取消操作 + + if (result.Data is TelegramPanel.Core.Services.RiskWarningAction action && action == TelegramPanel.Core.Services.RiskWarningAction.ExcludeRisky) + { + // 排除风险账号后继续 + accounts = batchCheck.SafeAccounts.ToList(); + if (accounts.Count == 0) + { + Snackbar.Add("排除风险账号后无剩余账号", Severity.Info); + return; + } + } + // else: 用户选择继续所有账号 + } + bool? confirm = await DialogService.ShowMessageBox( "确认修改", $"将对 {accounts.Count} 个账号批量修改 Bio(简介)。是否继续?", diff --git a/src/TelegramPanel.Web/Components/Dialogs/BatchChangeNicknameDialog.razor b/src/TelegramPanel.Web/Components/Dialogs/BatchChangeNicknameDialog.razor index 1122a22..edecd46 100644 --- a/src/TelegramPanel.Web/Components/Dialogs/BatchChangeNicknameDialog.razor +++ b/src/TelegramPanel.Web/Components/Dialogs/BatchChangeNicknameDialog.razor @@ -1,6 +1,7 @@ @namespace TelegramPanel.Web.Components.Dialogs @inject AccountManagementService AccountManagement @inject TelegramPanel.Core.Services.Telegram.AccountTelegramToolsService AccountTelegramTools +@inject TelegramPanel.Core.Services.AccountRiskService RiskService @inject ISnackbar Snackbar @inject IDialogService DialogService @using TelegramPanel.Data.Entities @@ -112,6 +113,38 @@ return; } + // 批量风控检查:修改昵称是敏感操作 + var batchCheck = RiskService.CheckBatchAccounts(accounts); + if (batchCheck.HasRiskyAccounts) + { + var parameters = new DialogParameters + { + ["Message"] = $"检测到 {batchCheck.RiskyCount} 个风险账号", + ["DetailedMessage"] = batchCheck.GetRiskySummary(), + ["ShowRecommendations"] = true, + ["ShowExcludeOption"] = true, + ["RiskyAccounts"] = batchCheck.RiskyAccounts.ToList() + }; + var options = new DialogOptions { CloseOnEscapeKey = true, MaxWidth = MaxWidth.Large }; + var dialog = DialogService.Show("批量操作风控警告", parameters, options); + var result = await dialog.Result; + + if (result.Canceled) + return; // 用户取消操作 + + if (result.Data is TelegramPanel.Core.Services.RiskWarningAction action && action == TelegramPanel.Core.Services.RiskWarningAction.ExcludeRisky) + { + // 排除风险账号后继续 + accounts = batchCheck.SafeAccounts.ToList(); + if (accounts.Count == 0) + { + Snackbar.Add("排除风险账号后无剩余账号", Severity.Info); + return; + } + } + // else: 用户选择继续所有账号 + } + bool? confirm = await DialogService.ShowMessageBox( "确认修改", $"将对 {accounts.Count} 个账号批量修改昵称。是否继续?", diff --git a/src/TelegramPanel.Web/Components/Dialogs/EditUserProfileDialog.razor b/src/TelegramPanel.Web/Components/Dialogs/EditUserProfileDialog.razor index 5df8afc..09da547 100644 --- a/src/TelegramPanel.Web/Components/Dialogs/EditUserProfileDialog.razor +++ b/src/TelegramPanel.Web/Components/Dialogs/EditUserProfileDialog.razor @@ -1,6 +1,7 @@ @namespace TelegramPanel.Web.Components.Dialogs @inject AccountManagementService AccountManagement @inject TelegramPanel.Core.Services.Telegram.AccountTelegramToolsService AccountTelegramTools +@inject TelegramPanel.Core.Services.AccountRiskService RiskService @inject ISnackbar Snackbar @inject IDialogService DialogService @using TelegramPanel.Data.Entities @@ -156,6 +157,26 @@ if (confirm != true) return; + // 风控检查:修改资料是敏感操作 + var riskCheck = RiskService.CheckLoginDuration(account); + if (riskCheck.IsRisky) + { + var parameters = new DialogParameters + { + ["Message"] = riskCheck.Message, + ["DetailedMessage"] = riskCheck.DetailedMessage, + ["ShowRecommendations"] = true + }; + var options = new DialogOptions { CloseOnEscapeKey = true, MaxWidth = MaxWidth.Medium }; + var dialog = DialogService.Show("风控警告", parameters, options); + var result = await dialog.Result; + if (result.Canceled) + { + saving = false; + return; + } + } + saving = true; try { diff --git a/src/TelegramPanel.Web/Components/Dialogs/RiskWarningDialog.razor b/src/TelegramPanel.Web/Components/Dialogs/RiskWarningDialog.razor new file mode 100644 index 0000000..e1db957 --- /dev/null +++ b/src/TelegramPanel.Web/Components/Dialogs/RiskWarningDialog.razor @@ -0,0 +1,110 @@ +@namespace TelegramPanel.Web.Components.Dialogs +@using TelegramPanel.Core.Services +@using TelegramPanel.Data.Entities + +@* 账号风控警告对话框 *@ + + + + + + ⚠️ 风控警告 + + + @Message + + @if (!string.IsNullOrWhiteSpace(DetailedMessage)) + { + + @DetailedMessage + + } + + + @if (ShowRecommendations) + { + + 建议操作: + + + + 等待满 24 小时后再进行敏感操作 + + + 降低操作频率,避免被 Telegram 风控系统标记 + + + 优先使用低风险操作替代 + + + } + + @if (RiskyAccounts != null && RiskyAccounts.Any()) + { + + 风险账号列表: + + + @foreach (var account in RiskyAccounts) + { + + @account.Phone + @if (account.LastLoginAt != null) + { + (登录 @account.GetLoginHoursFormatted() 小时) + } + + } + + } + + + + 取消操作 + + @if (ShowExcludeOption && RiskyAccounts != null && RiskyAccounts.Any()) + { + + 排除风险账号后继续 + + } + + 我了解风险,继续操作 + + + + +@code { + [CascadingParameter] + MudDialogInstance? MudDialog { get; set; } + + [Parameter] + public string Message { get; set; } = "存在风控风险"; + + [Parameter] + public string? DetailedMessage { get; set; } + + [Parameter] + public bool ShowRecommendations { get; set; } = true; + + [Parameter] + public bool ShowExcludeOption { get; set; } = false; + + [Parameter] + public List? RiskyAccounts { get; set; } + + private void Cancel() + { + MudDialog?.Close(DialogResult.Cancel()); + } + + private void Continue() + { + MudDialog?.Close(DialogResult.Ok(RiskWarningAction.Continue)); + } + + private void ExcludeRisky() + { + MudDialog?.Close(DialogResult.Ok(RiskWarningAction.ExcludeRisky)); + } +} diff --git a/src/TelegramPanel.Web/Components/Pages/Accounts.razor b/src/TelegramPanel.Web/Components/Pages/Accounts.razor index 47edfb5..8340501 100644 --- a/src/TelegramPanel.Web/Components/Pages/Accounts.razor +++ b/src/TelegramPanel.Web/Components/Pages/Accounts.razor @@ -2,10 +2,12 @@ @inject AccountManagementService AccountManagement @inject AccountCategoryManagementService CategoryManagement @inject AccountTelegramToolsService AccountTelegramTools +@inject TelegramPanel.Core.Services.AccountRiskService RiskService @inject ISnackbar Snackbar @inject IDialogService DialogService @inject NavigationManager Navigation @using TelegramPanel.Data.Entities +@using TelegramPanel.Web.Components.Dialogs @implements IDisposable 账号列表 - Telegram Panel @@ -370,11 +372,35 @@ loading = true; bool? probeResult = await DialogService.ShowMessageBox( "刷新 Telegram 状态", - "是否进行深度探测(将创建并删除一个测试频道,用于判断“创建频道接口是否被冻结”)?", + "是否进行深度探测(将创建并删除一个测试频道,用于判断【创建频道接口是否被冻结】)?", yesText: "深度探测", cancelText: "普通刷新"); var probe = probeResult == true; + + // 风控检查:深度探测是敏感操作 + if (probe) + { + var riskCheck = RiskService.CheckLoginDuration(account); + if (riskCheck.IsRisky) + { + var parameters = new DialogParameters + { + ["Message"] = riskCheck.Message, + ["DetailedMessage"] = riskCheck.DetailedMessage, + ["ShowRecommendations"] = true + }; + var options = new DialogOptions { CloseOnEscapeKey = true, MaxWidth = MaxWidth.Medium }; + var dialog = DialogService.Show("风控警告", parameters, options); + var dialogResult = await dialog.Result; + if (dialogResult.Canceled) + { + loading = false; + return; // 用户取消操作 + } + } + } + var result = await AccountTelegramTools.RefreshAccountStatusAsync(account.Id, probeCreateChannel: probe, cancellationToken: _pageCts.Token); telegramStatus[account.Id] = result; @@ -406,12 +432,53 @@ { bool? probeResult = await DialogService.ShowMessageBox( "批量刷新 Telegram 状态", - "是否进行深度探测(将对每个账号创建并删除一个测试频道,用于判断“创建频道接口是否被冻结”)?", + "是否进行深度探测(将对每个账号创建并删除一个测试频道,用于判断【创建频道接口是否被冻结】)?", yesText: "深度探测", cancelText: "普通刷新"); var probe = probeResult == true; var targets = filteredAccounts.ToList(); + + // 批量风控检查:深度探测是敏感操作 + if (probe && targets.Count > 0) + { + var batchCheck = RiskService.CheckBatchAccounts(targets); + if (batchCheck.HasRiskyAccounts) + { + var parameters = new DialogParameters + { + ["Message"] = $"检测到 {batchCheck.RiskyCount} 个风险账号", + ["DetailedMessage"] = batchCheck.GetRiskySummary(), + ["ShowRecommendations"] = true, + ["ShowExcludeOption"] = true, + ["RiskyAccounts"] = batchCheck.RiskyAccounts.ToList() + }; + var options = new DialogOptions { CloseOnEscapeKey = true, MaxWidth = MaxWidth.Large }; + var dialog = DialogService.Show("批量操作风控警告", parameters, options); + var dialogResult = await dialog.Result; + + if (dialogResult.Canceled) + { + loading = false; + return; // 用户取消操作 + } + + if (dialogResult.Data is TelegramPanel.Core.Services.RiskWarningAction action + && action == TelegramPanel.Core.Services.RiskWarningAction.ExcludeRisky) + { + // 排除风险账号后继续 + targets = batchCheck.SafeAccounts.ToList(); + if (targets.Count == 0) + { + Snackbar.Add("排除风险账号后无剩余账号", Severity.Info); + loading = false; + return; + } + } + // else: 用户选择继续所有账号 + } + } + foreach (var a in targets) { try diff --git a/src/TelegramPanel.Web/Components/Pages/ChannelCreate.razor b/src/TelegramPanel.Web/Components/Pages/ChannelCreate.razor index 19191a8..2c51de0 100644 --- a/src/TelegramPanel.Web/Components/Pages/ChannelCreate.razor +++ b/src/TelegramPanel.Web/Components/Pages/ChannelCreate.razor @@ -1,11 +1,14 @@ @page "/channels/create" @inject IChannelService ChannelService @inject AccountManagementService AccountManagement +@inject TelegramPanel.Core.Services.AccountRiskService RiskService @inject ChannelManagementService ChannelManagement @inject ChannelGroupManagementService ChannelGroupManagement @inject ISnackbar Snackbar @inject NavigationManager Navigation +@inject IDialogService DialogService @using TelegramPanel.Data.Entities +@using TelegramPanel.Web.Components.Dialogs 创建频道 - Telegram Panel @@ -139,6 +142,27 @@ return; } + // 风控检查:创建频道是敏感操作 + var account = await AccountManagement.GetAccountAsync(selectedAccountId); + if (account != null) + { + var riskCheck = RiskService.CheckLoginDuration(account); + if (riskCheck.IsRisky) + { + var parameters = new DialogParameters + { + ["Message"] = riskCheck.Message, + ["DetailedMessage"] = riskCheck.DetailedMessage, + ["ShowRecommendations"] = true + }; + var options = new DialogOptions { CloseOnEscapeKey = true, MaxWidth = MaxWidth.Medium }; + var dialog = DialogService.Show("风控警告", parameters, options); + var result = await dialog.Result; + if (result.Canceled) + return; // 用户取消操作 + } + } + creating = true; try