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 @@
-
+
频道列表