diff --git a/src/TelegramPanel.Web/Components/ModulePages/KickApiPage.razor b/src/TelegramPanel.Web/Components/ModulePages/KickApiPage.razor
index cbc38ef..5b19542 100644
--- a/src/TelegramPanel.Web/Components/ModulePages/KickApiPage.razor
+++ b/src/TelegramPanel.Web/Components/ModulePages/KickApiPage.razor
@@ -32,11 +32,41 @@
-
+
- @if (!useAllChats && selectedBotId != 0)
+ @if (selectedBotId != 0 && !useAllChats)
{
+
+ 选择分类:@selectedCategories.Count / @categories.Count
+
+
+ 全选
+
+
+ 清空
+
+
+
+
+
+ 分类
+ 说明
+
+
+ @context.Name
+ @(!string.IsNullOrWhiteSpace(context.Description) ? context.Description : "-")
+
+
+ 暂无分类
+
+
+
+
+
@@ -62,13 +92,25 @@
private bool loading = true;
private List bots = new();
+ private List categories = new();
private int selectedBotId = 0;
private long userId;
private bool permanentBan;
private bool useAllChats = true;
+ private HashSet selectedCategories = new();
+ private bool includeUncategorized;
private string chatIdsText = "";
- private bool CanSubmit => !loading && userId > 0 && (selectedBotId == 0 || bots.Any(x => x.Id == selectedBotId));
+ private bool CanSubmit
+ => !loading
+ && userId > 0
+ && (selectedBotId == 0 || bots.Any(x => x.Id == selectedBotId))
+ && (
+ selectedBotId == 0
+ || useAllChats
+ || includeUncategorized
+ || selectedCategories.Count > 0
+ || !string.IsNullOrWhiteSpace(chatIdsText));
protected override async Task OnInitializedAsync()
{
@@ -78,6 +120,17 @@
.Where(b => b.IsActive)
.OrderBy(b => b.Id)
.ToList();
+
+ categories = (await BotManagement.GetCategoriesAsync())
+ .OrderBy(c => c.Name, StringComparer.OrdinalIgnoreCase)
+ .ToList();
+
+ // 默认不对“全部机器人/全部频道”开火
+ if (bots.Count > 0)
+ {
+ selectedBotId = bots[0].Id;
+ useAllChats = false;
+ }
}
catch (Exception ex)
{
@@ -91,9 +144,40 @@
private async Task OnSelectedBotChanged(int id)
{
+ var previous = selectedBotId;
selectedBotId = id;
if (selectedBotId == 0)
useAllChats = true;
+ else if (previous == 0)
+ useAllChats = false;
+
+ selectedCategories = new HashSet();
+ includeUncategorized = false;
+ chatIdsText = "";
+ await Task.CompletedTask;
+ }
+
+ private async Task OnUseAllChatsChanged()
+ {
+ if (useAllChats)
+ {
+ selectedCategories = new HashSet();
+ includeUncategorized = false;
+ chatIdsText = "";
+ }
+ await Task.CompletedTask;
+ }
+
+ private async Task SelectAllCategories()
+ {
+ selectedCategories = categories.ToHashSet();
+ await Task.CompletedTask;
+ }
+
+ private async Task ClearCategories()
+ {
+ selectedCategories = new HashSet();
+ includeUncategorized = false;
await Task.CompletedTask;
}
@@ -104,12 +188,62 @@
var botId = selectedBotId;
var runUseAllChats = botId == 0 ? true : useAllChats;
- var chatIds = runUseAllChats ? new List() : ParseChatIds(chatIdsText);
loading = true;
try
{
- var total = await CountTargetsAsync(botId, runUseAllChats, chatIds);
+ var total = 0;
+ var targetChatIds = new List();
+
+ if (botId == 0)
+ {
+ foreach (var b in bots)
+ total += (await BotManagement.GetChatsAsync(b.Id)).Count();
+ }
+ else
+ {
+ var chats = (await BotManagement.GetChatsAsync(botId)).ToList();
+ if (runUseAllChats)
+ {
+ total = chats.Count;
+ }
+ else
+ {
+ var selectedIds = new HashSet();
+ var selectedCategoryIdSet = selectedCategories.Select(x => x.Id).ToHashSet();
+
+ if (selectedCategoryIdSet.Count > 0 || includeUncategorized)
+ {
+ foreach (var c in chats)
+ {
+ if (c.CategoryId.HasValue)
+ {
+ if (selectedCategoryIdSet.Contains(c.CategoryId.Value))
+ selectedIds.Add(c.TelegramId);
+ }
+ else
+ {
+ if (includeUncategorized)
+ selectedIds.Add(c.TelegramId);
+ }
+ }
+ }
+
+ foreach (var id in ParseChatIds(chatIdsText))
+ selectedIds.Add(id);
+
+ if (selectedIds.Count > 0)
+ {
+ total = chats.Count(c => selectedIds.Contains(c.TelegramId));
+ var knownIds = chats.Select(c => c.TelegramId).ToHashSet();
+ targetChatIds = selectedIds
+ .Where(knownIds.Contains)
+ .OrderBy(x => x)
+ .ToList();
+ }
+ }
+ }
+
if (total <= 0)
{
Snackbar.Add("未匹配到任何可操作的频道/群组(请先同步 Bot 频道数据,或检查 chat_id 列表)", Severity.Warning);
@@ -121,7 +255,7 @@
ApiName = "模块页面",
BotId = botId,
UseAllChats = runUseAllChats,
- ChatIds = chatIds.Where(x => x != 0).Distinct().OrderBy(x => x).ToList(),
+ ChatIds = runUseAllChats ? new List() : targetChatIds,
UserId = userId,
PermanentBan = permanentBan,
RequestedAtUtc = DateTime.UtcNow
@@ -150,31 +284,6 @@
}
}
- private async Task CountTargetsAsync(int botId, bool runUseAllChats, IReadOnlyCollection chatIds)
- {
- if (botId > 0)
- {
- var chats = (await BotManagement.GetChatsAsync(botId)).ToList();
- if (!runUseAllChats && chatIds.Count > 0)
- chats = chats.Where(c => chatIds.Contains(c.TelegramId)).ToList();
- return chats.Count;
- }
-
- // botId==0: all bots (force useAllChats)
- var botsList = (await BotManagement.GetAllBotsAsync())
- .Where(b => b.IsActive)
- .OrderBy(b => b.Id)
- .ToList();
-
- var total = 0;
- foreach (var b in botsList)
- {
- var chats = await BotManagement.GetChatsAsync(b.Id);
- total += chats.Count();
- }
- return total;
- }
-
private static List ParseChatIds(string raw)
{
raw = (raw ?? "").Trim();