From eb26b9b7efcadbac059ae9f01b8b1ce9883bc4c8 Mon Sep 17 00:00:00 2001 From: meoacgx Date: Fri, 19 Dec 2025 19:00:18 +0800 Subject: [PATCH] =?UTF-8?q?=E9=87=8D=E6=9E=84Bot=E9=A2=91=E9=81=93?= =?UTF-8?q?=E9=A1=B5=E9=9D=A2=EF=BC=9A=E5=8D=95=E9=A1=B5=E5=88=87=E6=8D=A2?= =?UTF-8?q?=E6=9C=BA=E5=99=A8=E4=BA=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Components/Pages/BotChannels.razor | 306 --------------- .../Components/Pages/BotChannelsHome.razor | 366 +++++++++++++++++- .../Components/Pages/Bots.razor | 4 +- 3 files changed, 352 insertions(+), 324 deletions(-) delete mode 100644 src/TelegramPanel.Web/Components/Pages/BotChannels.razor diff --git a/src/TelegramPanel.Web/Components/Pages/BotChannels.razor b/src/TelegramPanel.Web/Components/Pages/BotChannels.razor deleted file mode 100644 index 142e340..0000000 --- a/src/TelegramPanel.Web/Components/Pages/BotChannels.razor +++ /dev/null @@ -1,306 +0,0 @@ -@page "/bots/{BotId:int}/channels" -@inject BotManagementService BotManagement -@inject TelegramPanel.Core.Services.Telegram.BotTelegramService BotTelegram -@inject ISnackbar Snackbar -@inject IDialogService DialogService -@inject NavigationManager Navigation -@inject IJSRuntime JS -@using TelegramPanel.Data.Entities - -Bot 频道 - Telegram Panel - -Bot 频道 -@if (bot != null) -{ - @bot.Name @(!string.IsNullOrWhiteSpace(bot.Username) ? $"(@{bot.Username})" : "") -} - - - - - - 频道 (@channels.Count) - - - - 全部分类 - 未分类 - @foreach (var c in categories) - { - @c.Name - } - - - - - - 同步 Bot 频道 - - - - 导出邀请(已选) - - - - 刷新 - - - - - 频道名称 - 用户名 - 分类 - 最后同步 - 操作 - - - - @context.Title - - - @if (!string.IsNullOrWhiteSpace(context.Username)) - { - @context.Username - } - else - { - - - } - - - - 未分类 - @foreach (var c in categories) - { - @c.Name - } - - - @context.SyncedAt.ToString("yyyy-MM-dd HH:mm") - - - 复制链接 - 复制邀请 - - - - - 暂无频道 - - - - - - - - 新增分类 - - - - - - - - - - 创建 - - - - - - -@code { - [Parameter] public int BotId { get; set; } - - private bool loading = true; - private Bot? bot; - private List categories = new(); - private List channels = new(); - private HashSet selected = new(); - - private int filterCategoryId = 0; - private string search = ""; - - private string newCategoryName = ""; - private string newCategoryDesc = ""; - - private IEnumerable filtered => - channels.Where(c => - { - if (filterCategoryId == -1 && c.CategoryId != null) - return false; - if (filterCategoryId > 0 && c.CategoryId != filterCategoryId) - return false; - - if (string.IsNullOrWhiteSpace(search)) - return true; - - return c.Title.Contains(search, StringComparison.OrdinalIgnoreCase) - || (c.Username?.Contains(search, StringComparison.OrdinalIgnoreCase) ?? false); - }); - - protected override async Task OnInitializedAsync() - { - await LoadAll(); - } - - private async Task LoadAll() - { - loading = true; - try - { - bot = await BotManagement.GetBotAsync(BotId); - if (bot == null) - { - Snackbar.Add("机器人不存在", Severity.Error); - Navigation.NavigateTo("/bots"); - return; - } - - categories = (await BotManagement.GetCategoriesAsync(BotId)).ToList(); - channels = (await BotManagement.GetChannelsAsync(BotId)).ToList(); - - // 清理已选 - var ids = channels.Select(x => x.Id).ToHashSet(); - selected = selected.Where(x => ids.Contains(x.Id)).ToHashSet(); - } - catch (Exception ex) - { - Snackbar.Add($"加载失败:{ex.Message}", Severity.Error); - } - finally - { - loading = false; - } - } - - private async Task Sync() - { - loading = true; - try - { - var count = await BotTelegram.SyncBotChannelsAsync(BotId, CancellationToken.None); - Snackbar.Add($"同步完成:影响 {count} 个频道", Severity.Success); - await LoadAll(); - } - catch (Exception ex) - { - Snackbar.Add($"同步失败:{ex.Message}", Severity.Error); - } - finally - { - loading = false; - } - } - - private async Task CreateCategoryAsync() - { - if (string.IsNullOrWhiteSpace(newCategoryName)) - { - Snackbar.Add("请输入分类名称", Severity.Warning); - return; - } - - loading = true; - try - { - await BotManagement.CreateCategoryAsync(BotId, newCategoryName, newCategoryDesc); - newCategoryName = ""; - newCategoryDesc = ""; - await LoadAll(); - Snackbar.Add("分类已创建", Severity.Success); - } - catch (Exception ex) - { - Snackbar.Add($"创建失败:{ex.Message}", Severity.Error); - } - finally - { - loading = false; - } - } - - private async Task SetCategoryAsync(BotChannel channel, int? categoryId) - { - try - { - await BotManagement.SetChannelCategoryAsync(channel.Id, categoryId); - channel.CategoryId = categoryId; - Snackbar.Add("已保存分类", Severity.Success); - } - catch (Exception ex) - { - Snackbar.Add($"保存失败:{ex.Message}", Severity.Error); - } - } - - private async Task CopyPublicLinkAsync(BotChannel channel) - { - try - { - if (string.IsNullOrWhiteSpace(channel.Username)) - { - Snackbar.Add("该频道没有公开链接(无用户名)", Severity.Info); - return; - } - - var link = $"https://t.me/{channel.Username.Trim().TrimStart('@')}"; - await JS.InvokeVoidAsync("telegramPanel.copyText", link); - Snackbar.Add("已复制链接", Severity.Success); - } - catch (Exception ex) - { - Snackbar.Add($"复制失败:{ex.Message}", Severity.Error); - } - } - - private async Task CopyInviteAsync(BotChannel channel) - { - loading = true; - try - { - var link = await BotTelegram.ExportInviteLinkAsync(BotId, channel.TelegramId, CancellationToken.None); - await JS.InvokeVoidAsync("telegramPanel.copyText", link); - Snackbar.Add("已复制邀请链接", Severity.Success); - } - catch (Exception ex) - { - Snackbar.Add($"获取邀请失败:{ex.Message}", Severity.Error); - } - finally - { - loading = false; - } - } - - private async Task ExportInvites() - { - if (selected.Count == 0) - { - Snackbar.Add("请先选择频道", Severity.Info); - return; - } - - bool? result = await DialogService.ShowMessageBox( - "确认导出", - $"将为 {selected.Count} 个频道生成邀请链接并导出(需要机器人具备管理权限)。是否继续?", - yesText: "继续", cancelText: "取消"); - - if (result != true) - return; - - var ids = string.Join(",", selected.Select(x => x.TelegramId)); - var url = $"/downloads/bots/{BotId}/invites.txt?ids={Uri.EscapeDataString(ids)}"; - Navigation.NavigateTo(url, forceLoad: true); - await Task.CompletedTask; - } -} diff --git a/src/TelegramPanel.Web/Components/Pages/BotChannelsHome.razor b/src/TelegramPanel.Web/Components/Pages/BotChannelsHome.razor index d733391..27a540e 100644 --- a/src/TelegramPanel.Web/Components/Pages/BotChannelsHome.razor +++ b/src/TelegramPanel.Web/Components/Pages/BotChannelsHome.razor @@ -1,8 +1,12 @@ @page "/bots/channels" @inject BotManagementService BotManagement +@inject TelegramPanel.Core.Services.Telegram.BotTelegramService BotTelegram @inject ISnackbar Snackbar +@inject IDialogService DialogService @inject NavigationManager Navigation +@inject IJSRuntime JS @using TelegramPanel.Data.Entities +@using TelegramPanel.Web.Components.Dialogs Bot 频道 - Telegram Panel @@ -10,44 +14,374 @@ - - -- 请选择机器人 -- - @foreach (var b in bots) - { - @b.Name - } - + + + + -- 请选择机器人 -- + @foreach (var b in bots) + { + @b.Name + } + - - 打开频道列表 - + + 频道 (@channels.Count) + + + + + + 全部分类 + 未分类 + @foreach (var c in categories) + { + @c.Name + } + + + + + + 同步 + + + + 导出邀请(已选) + + + + 刷新 + + + + + 频道名称 + 用户名 + 分类 + 最后同步 + 操作 + + + + @context.Title + + + @if (!string.IsNullOrWhiteSpace(context.Username)) + { + @context.Username + } + else + { + - + } + + + + 未分类 + @foreach (var c in categories) + { + @c.Name + } + + + @context.SyncedAt.ToString("yyyy-MM-dd HH:mm") + + + 复制链接 + + 查看详情 + 编辑频道 + + + + + @if (selectedBotId <= 0) + { + 请先选择机器人 + } + else + { + 暂无频道 + } + + +@if (selectedBotId > 0) +{ + + + 新增分类 + + + + + + + + + + 创建 + + + + + +} + @code { + [SupplyParameterFromQuery(Name = "botId")] + public int? BotIdQuery { get; set; } + private List bots = new(); + private Bot? selectedBot; private int selectedBotId = 0; + private bool loading = true; + private List categories = new(); + private List channels = new(); + + private HashSet selected = new(); + + private int filterCategoryId = 0; + private string search = ""; + + private string newCategoryName = ""; + private string newCategoryDesc = ""; + + private IEnumerable filtered => selectedBotId <= 0 + ? Enumerable.Empty() + : channels.Where(c => + { + if (filterCategoryId == -1 && c.CategoryId != null) + return false; + if (filterCategoryId > 0 && c.CategoryId != filterCategoryId) + return false; + + if (string.IsNullOrWhiteSpace(search)) + return true; + + return c.Title.Contains(search, StringComparison.OrdinalIgnoreCase) + || (c.Username?.Contains(search, StringComparison.OrdinalIgnoreCase) ?? false); + }); + protected override async Task OnInitializedAsync() { try { bots = (await BotManagement.GetAllBotsAsync()).ToList(); + + if (BotIdQuery is > 0 && bots.Any(x => x.Id == BotIdQuery.Value)) + { + selectedBotId = BotIdQuery.Value; + await LoadBotData(); + } + else if (bots.Count == 1) + { + selectedBotId = bots[0].Id; + await LoadBotData(); + } } catch (Exception ex) { Snackbar.Add($"加载机器人失败:{ex.Message}", Severity.Error); } + finally + { + loading = false; + } } - private Task Go() + private async Task OnSelectedBotChanged(int botId) + { + if (selectedBotId == botId) + return; + + selectedBotId = botId; + filterCategoryId = 0; + search = ""; + selected.Clear(); + + if (selectedBotId <= 0) + { + selectedBot = null; + categories.Clear(); + channels.Clear(); + Navigation.NavigateTo("/bots/channels", replace: true); + return; + } + + Navigation.NavigateTo($"/bots/channels?botId={selectedBotId}", replace: true); + await LoadBotData(); + } + + private async Task LoadBotData() { if (selectedBotId <= 0) - return Task.CompletedTask; + return; - Navigation.NavigateTo($"/bots/{selectedBotId}/channels"); - return Task.CompletedTask; + loading = true; + try + { + selectedBot = await BotManagement.GetBotAsync(selectedBotId); + if (selectedBot == null) + { + Snackbar.Add("机器人不存在", Severity.Error); + selectedBotId = 0; + return; + } + + categories = (await BotManagement.GetCategoriesAsync(selectedBotId)).ToList(); + channels = (await BotManagement.GetChannelsAsync(selectedBotId)).ToList(); + + // 清理已选 + var ids = channels.Select(x => x.Id).ToHashSet(); + selected = selected.Where(x => ids.Contains(x.Id)).ToHashSet(); + } + catch (Exception ex) + { + Snackbar.Add($"加载失败:{ex.Message}", Severity.Error); + } + finally + { + loading = false; + } + } + + private async Task Sync() + { + if (selectedBotId <= 0) + return; + + loading = true; + try + { + var count = await BotTelegram.SyncBotChannelsAsync(selectedBotId, CancellationToken.None); + Snackbar.Add($"同步完成:影响 {count} 个频道", Severity.Success); + await LoadBotData(); + } + catch (Exception ex) + { + Snackbar.Add($"同步失败:{ex.Message}", Severity.Error); + } + finally + { + loading = false; + } + } + + private async Task CreateCategoryAsync() + { + if (selectedBotId <= 0) + return; + + if (string.IsNullOrWhiteSpace(newCategoryName)) + { + Snackbar.Add("请输入分类名称", Severity.Warning); + return; + } + + loading = true; + try + { + await BotManagement.CreateCategoryAsync(selectedBotId, newCategoryName, newCategoryDesc); + newCategoryName = ""; + newCategoryDesc = ""; + await LoadBotData(); + Snackbar.Add("分类已创建", Severity.Success); + } + catch (Exception ex) + { + Snackbar.Add($"创建失败:{ex.Message}", Severity.Error); + } + finally + { + loading = false; + } + } + + private async Task SetCategoryAsync(BotChannel channel, int? categoryId) + { + try + { + await BotManagement.SetChannelCategoryAsync(channel.Id, categoryId); + channel.CategoryId = categoryId; + Snackbar.Add("已保存分类", Severity.Success); + } + catch (Exception ex) + { + Snackbar.Add($"保存失败:{ex.Message}", Severity.Error); + } + } + + private async Task CopyLinkAsync(BotChannel channel) + { + if (selectedBotId <= 0) + return; + + loading = true; + try + { + var link = await BotTelegram.ExportInviteLinkAsync(selectedBotId, channel.TelegramId, CancellationToken.None); + await JS.InvokeVoidAsync("telegramPanel.copyText", link); + Snackbar.Add("已复制链接", Severity.Success); + } + catch (Exception ex) + { + Snackbar.Add($"复制失败:{ex.Message}", Severity.Error); + } + finally + { + loading = false; + } + } + + private async Task ExportInvites() + { + if (selectedBotId <= 0) + return; + + if (selected.Count == 0) + { + Snackbar.Add("请先选择频道", Severity.Info); + return; + } + + bool? result = await DialogService.ShowMessageBox( + "确认导出", + $"将为 {selected.Count} 个频道生成邀请链接并导出(需要机器人具备管理权限)。是否继续?", + yesText: "继续", cancelText: "取消"); + + if (result != true) + return; + + var ids = string.Join(",", selected.Select(x => x.TelegramId)); + var url = $"/downloads/bots/{selectedBotId}/invites.txt?ids={Uri.EscapeDataString(ids)}"; + Navigation.NavigateTo(url, forceLoad: true); + await Task.CompletedTask; + } + + private async Task ShowDetailsAsync(BotChannel channel) + { + // 详情弹窗在下一步实现,这里先占位避免空点击 + Snackbar.Add("Bot 频道详情开发中…", Severity.Info); + await Task.CompletedTask; + } + + private async Task EditChannelAsync(BotChannel channel) + { + // 编辑弹窗在下一步实现,这里先占位避免空点击 + Snackbar.Add("Bot 频道编辑开发中…", Severity.Info); + await Task.CompletedTask; } } - diff --git a/src/TelegramPanel.Web/Components/Pages/Bots.razor b/src/TelegramPanel.Web/Components/Pages/Bots.razor index cab0ef9..e0c93e4 100644 --- a/src/TelegramPanel.Web/Components/Pages/Bots.razor +++ b/src/TelegramPanel.Web/Components/Pages/Bots.razor @@ -59,8 +59,8 @@ - + 频道列表