using Admin.NET.Core; using Admin.NET.Plugin.AiDOP.Entity; using Admin.NET.Plugin.AiDOP.Infrastructure; using Admin.NET.Plugin.AiDOP.SmartOps; using Furion.Schedule; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; namespace Admin.NET.Plugin.AiDOP.Job; [JobDetail("job_smart_ops_action_reminder", Description = "智慧诊断行动项到期/逾期提醒", GroupName = "default", Concurrent = false)] [Daily(TriggerId = "trigger_smart_ops_action_reminder", Description = "每日扫描改善行动项提醒")] public class SmartOpsImprovementActionReminderJob : IJob { private readonly IServiceScopeFactory _scopeFactory; private readonly ILogger _logger; public SmartOpsImprovementActionReminderJob(IServiceScopeFactory scopeFactory, ILoggerFactory loggerFactory) { _scopeFactory = scopeFactory; _logger = loggerFactory.CreateLogger(nameof(SmartOpsImprovementActionReminderJob)); } public async Task ExecuteAsync(JobExecutingContext context, CancellationToken stoppingToken) { using var scope = _scopeFactory.CreateScope(); var rootDb = scope.ServiceProvider.GetRequiredService(); var today = DateTime.Today; List tenantIds; try { tenantIds = await rootDb.CopyNew().Queryable() .Where(x => x.TenantId != null && x.TenantId > 0 && x.TenantId != SmartOpsTrustedScopeRules.PlatformTenantId) .Select(x => x.TenantId!.Value) .Distinct() .ToListAsync(stoppingToken); } catch (Exception ex) { _logger.LogWarning(ex, "行动项提醒作业读取租户失败"); return; } var service = new SmartOpsImprovementActionService(rootDb); foreach (var tenantId in tenantIds) { stoppingToken.ThrowIfCancellationRequested(); try { var db = rootDb.CopyNew(); var sent = await service.SendDueRemindersAsync(db, tenantId, today); if (sent > 0) _logger.LogInformation("行动项提醒 tenant={TenantId} sent={Sent}", tenantId, sent); } catch (Exception ex) { _logger.LogError(ex, "行动项提醒失败 tenant={TenantId}", tenantId); } } } }