chore: 全面规范化代码,遵循 CLAUDE.md 编码规范
- C# 文件命名改为 snake_case(28 个文件重命名) - C# 类转换为主构造函数(8 个类) - 空 catch 添加异常类型(2 处) - 新建 GlobalUsings.cs(Health.Infrastructure、Health.WebApi) - Flutter 移除 go_router,改用 Riverpod 路由栈 - Flutter 移除 flutter_secure_storage,改用 sqflite 持久化 - 修复 Flutter 构建路径(Flutter SDK 迁至 D 盘) - 后端端口改为 0.0.0.0:5000,支持局域网访问
This commit is contained in:
@@ -0,0 +1,61 @@
|
||||
namespace Health.WebApi.BackgroundServices;
|
||||
|
||||
/// <summary>
|
||||
/// 用药提醒定时扫描服务(每分钟检查一次)
|
||||
/// </summary>
|
||||
public sealed class MedicationReminderService(IServiceScopeFactory scopeFactory, ILogger<MedicationReminderService> logger) : BackgroundService
|
||||
{
|
||||
private readonly IServiceScopeFactory _scopeFactory = scopeFactory;
|
||||
private readonly ILogger<MedicationReminderService> _logger = logger;
|
||||
|
||||
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
|
||||
{
|
||||
_logger.LogInformation("用药提醒服务已启动");
|
||||
|
||||
while (!stoppingToken.IsCancellationRequested)
|
||||
{
|
||||
try
|
||||
{
|
||||
await ProcessReminders(stoppingToken);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "用药提醒扫描异常");
|
||||
}
|
||||
|
||||
await Task.Delay(TimeSpan.FromMinutes(1), stoppingToken);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task ProcessReminders(CancellationToken ct)
|
||||
{
|
||||
using var scope = _scopeFactory.CreateScope();
|
||||
var db = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||
// 使用北京时间(UTC+8)
|
||||
var beijingNow = DateTime.UtcNow.AddHours(8);
|
||||
var beijingTime = TimeOnly.FromDateTime(beijingNow);
|
||||
var today = DateOnly.FromDateTime(beijingNow);
|
||||
|
||||
// 查询:启用的用药计划 AND 服药时间在当前时间前后5分钟窗口内(防止服务重启错过提醒)
|
||||
var windowStart = beijingTime.AddMinutes(-5);
|
||||
var medications = await db.Medications
|
||||
.Where(m => m.IsActive)
|
||||
.Where(m => m.TimeOfDay.Any(t => t >= windowStart && t <= beijingTime))
|
||||
.ToListAsync(ct);
|
||||
|
||||
foreach (var med in medications)
|
||||
{
|
||||
// 检查今天是否已打卡
|
||||
var alreadyLogged = await db.MedicationLogs
|
||||
.AnyAsync(l => l.MedicationId == med.Id
|
||||
&& l.CreatedAt.Date == beijingNow.Date
|
||||
&& l.Status == MedicationLogStatus.Taken, ct);
|
||||
|
||||
if (alreadyLogged) continue;
|
||||
|
||||
// TODO: 调用极光推送发送用药提醒
|
||||
_logger.LogInformation("用药提醒: 用户 {UserId} 药品 {Name} {Dosage} 时间 {Time}",
|
||||
med.UserId, med.Name, med.Dosage, beijingTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user