From a7929b1eed89a28c86ac7d7feec8bc5704845a8b Mon Sep 17 00:00:00 2001 From: meoacgx Date: Wed, 4 Mar 2026 22:20:36 +0800 Subject: [PATCH] =?UTF-8?q?fix(tasks):=20=E7=AE=80=E5=8C=96Bot=E7=AE=A1?= =?UTF-8?q?=E7=90=86=E5=91=98=E4=BB=BB=E5=8A=A1=E8=AF=A6=E6=83=85=E5=B9=B6?= =?UTF-8?q?=E4=BF=AE=E6=AD=A3=E5=AE=8C=E6=88=90=E7=8A=B6=E6=80=81=E5=B1=95?= =?UTF-8?q?=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Components/Pages/Tasks.razor | 89 +++++++++++++++++-- .../Services/BatchTaskBackgroundService.cs | 6 +- 2 files changed, 85 insertions(+), 10 deletions(-) diff --git a/src/TelegramPanel.Web/Components/Pages/Tasks.razor b/src/TelegramPanel.Web/Components/Pages/Tasks.razor index bceb1d0..a69dc8d 100644 --- a/src/TelegramPanel.Web/Components/Pages/Tasks.razor +++ b/src/TelegramPanel.Web/Components/Pages/Tasks.razor @@ -6,6 +6,8 @@ @inject IDialogService DialogService @using TelegramPanel.Data.Entities @using TelegramPanel.Core.BatchTasks +@using System.Text.Json +@using TelegramPanel.Web.Services @implements IDisposable 任务中心 - Telegram Panel @@ -62,10 +64,10 @@ @GetTaskTypeName(context.TaskType) - @GetStatusName(context.Status) + @GetStatusName(GetDisplayStatus(context)) - + @context.Completed / @context.Total (@context.Failed 失败) @@ -82,12 +84,12 @@ - @if (context.Status == "pending" || context.Status == "running") + @if (GetDisplayStatus(context) == "pending" || GetDisplayStatus(context) == "running") { } - @if (context.Status == "completed" || context.Status == "failed") + @if (GetDisplayStatus(context) == "completed" || GetDisplayStatus(context) == "failed") { @@ -112,7 +114,7 @@ private IEnumerable filteredTasks => tasks.Where(t => - (filterStatus == "all" || t.Status == filterStatus) && + (filterStatus == "all" || GetDisplayStatus(t) == filterStatus) && (filterCategory == "all" || GetCategory(t.TaskType) == filterCategory)); private IEnumerable AvailableCategories => @@ -277,11 +279,20 @@ _ => Color.Default }; + private static string GetDisplayStatus(BatchTask task) + { + if (task.Status == "failed" && task.CompletedAt.HasValue && task.Total > 0 && task.Completed >= task.Total) + return "completed"; + + return task.Status; + } + private void ShowTaskDetails(BatchTask task) { var createdAt = TimeZone.Format(task.CreatedAt, "yyyy-MM-dd HH:mm"); + var displayStatus = GetDisplayStatus(task); var details = $"任务类型: {GetTaskTypeName(task.TaskType)}\n" + - $"状态: {GetStatusName(task.Status)}\n" + + $"状态: {GetStatusName(displayStatus)}\n" + $"总数: {task.Total}\n" + $"已完成: {task.Completed}\n" + $"失败: {task.Failed}\n" + @@ -293,7 +304,10 @@ if (task.CompletedAt.HasValue) details += $"完成时间: {TimeZone.Format(task.CompletedAt.Value, "yyyy-MM-dd HH:mm")}\n"; - if (!string.IsNullOrEmpty(task.Config)) + var failureLines = ExtractBotAdminFailureLines(task); + if (failureLines.Count > 0) + details += $"\n失败频道:\n{string.Join('\n', failureLines)}"; + else if (!IsBotAdminTask(task.TaskType) && !string.IsNullOrEmpty(task.Config)) details += $"\n配置信息:\n{task.Config}"; var html = System.Net.WebUtility.HtmlEncode(details) @@ -302,6 +316,67 @@ DialogService.ShowMessageBox("任务详情", (MarkupString)html); } + private static bool IsBotAdminTask(string taskType) => + taskType is BatchTaskTypes.BotChannelSetAdminsByAccount or BatchTaskTypes.BotSetAdmins; + + private static List ExtractBotAdminFailureLines(BatchTask task) + { + var lines = new List(); + if (!IsBotAdminTask(task.TaskType) || string.IsNullOrWhiteSpace(task.Config) || task.Failed <= 0) + return lines; + + try + { + using var doc = JsonDocument.Parse(task.Config); + var root = doc.RootElement; + + if (root.TryGetProperty("FailureLines", out var failureLinesElement) + && failureLinesElement.ValueKind == JsonValueKind.Array) + { + foreach (var lineElement in failureLinesElement.EnumerateArray()) + { + var line = (lineElement.GetString() ?? string.Empty).Trim(); + if (line.Length > 0) + lines.Add(line); + } + + if (lines.Count > 0) + return lines; + } + + if (root.TryGetProperty("Failures", out var failuresElement) + && failuresElement.ValueKind == JsonValueKind.Array) + { + var failures = new List(); + foreach (var item in failuresElement.EnumerateArray()) + { + if (item.ValueKind != JsonValueKind.Object) + continue; + + var failure = new BotAdminTaskFailureItem + { + ChannelTelegramId = item.TryGetProperty("ChannelTelegramId", out var channelId) && channelId.TryGetInt64(out var id) ? id : 0, + ChannelTitle = item.TryGetProperty("ChannelTitle", out var channelTitle) ? channelTitle.GetString() ?? string.Empty : string.Empty, + Username = item.TryGetProperty("Username", out var username) ? username.GetString() : null, + UserId = item.TryGetProperty("UserId", out var userId) && userId.TryGetInt64(out var uid) ? uid : null, + Reason = item.TryGetProperty("Reason", out var reason) ? reason.GetString() ?? string.Empty : string.Empty + }; + + failures.Add(failure); + } + + if (failures.Count > 0) + lines = BotAdminTaskFailureFormatter.BuildLines(failures); + } + } + catch + { + // 配置异常时回退到默认展示,不中断详情弹窗。 + } + + return lines; + } + private async Task CancelTask(int id) { bool? result = await DialogService.ShowMessageBox( diff --git a/src/TelegramPanel.Web/Services/BatchTaskBackgroundService.cs b/src/TelegramPanel.Web/Services/BatchTaskBackgroundService.cs index 0ab3d14..8217592 100644 --- a/src/TelegramPanel.Web/Services/BatchTaskBackgroundService.cs +++ b/src/TelegramPanel.Web/Services/BatchTaskBackgroundService.cs @@ -160,9 +160,9 @@ public sealed class BatchTaskBackgroundService : BackgroundService if (latest != null && latest.Status != "running") return; - await taskManagement.CompleteTaskAsync(pending.Id, success: failed == 0); - _logger.LogInformation("Batch task completed: {TaskId} {TaskType} (ok={Ok}, completed={Completed}, failed={Failed})", - pending.Id, pending.TaskType, failed == 0, completed, failed); + await taskManagement.CompleteTaskAsync(pending.Id, success: true); + _logger.LogInformation("Batch task completed: {TaskId} {TaskType} (completed={Completed}, failed={Failed})", + pending.Id, pending.TaskType, completed, failed); } catch (Exception ex) {