refactor: 重构蓝牙设备页与新增设备页的扫描-连接-录入流程

- 通用 BLE 健康设备识别(血压计/血糖仪/体重秤/血氧仪 标准 service UUID)
- 蓝牙设备页静默自动同步:仅匹配已绑定的设备名+类型,收到数据后变绿
- 新增设备页:扫描所有支持类型设备 → 选连接 → 绑定 + 同步首次数据
- 修复 read 缓存导致的重复录入循环(删除主动 read,依赖 indicate 推送)
- 修复 isConnected 缓存状态导致连接异常(强制先 disconnect 再 connect)
- 录入弹窗:血压心率同等级展示、3 秒自动关闭/手动确认
- 顺手更新本机开发 IP 与清理过时设计文档
This commit is contained in:
MingNian
2026-06-28 22:53:35 +08:00
parent a748c316f2
commit 4507083f3f
20 changed files with 1936 additions and 4428 deletions

View File

@@ -1,5 +1,7 @@
using System.Security.Claims;
using System.Text.Json;
using Health.Application.Notifications;
using Health.Domain.Enums;
namespace Health.WebApi.Endpoints;
@@ -96,6 +98,48 @@ public static class NotificationEndpoints
if (body.HealthRecordReminderWeight.HasValue) pref.HealthRecordReminderWeight = body.HealthRecordReminderWeight.Value;
pref.UpdatedAt = DateTime.UtcNow;
await db.SaveChangesAsync(ct);
// 保存后立即检查该用户是否需要健康录入提醒,不用等到 9:00/12:00
if (body.HealthRecordReminder is true && pref.HealthRecordReminder)
{
var nowCst = DateTime.UtcNow.AddHours(8);
var todayStart = nowCst.Date.AddHours(-8);
var todayEnd = todayStart.AddDays(1);
var recordedTypes = await db.HealthRecords
.Where(r => r.UserId == userId && r.RecordedAt >= todayStart && r.RecordedAt < todayEnd)
.Select(r => r.MetricType)
.Distinct()
.ToListAsync(ct);
var missing = new List<(HealthMetricType type, bool enabled, string label)>
{
(HealthMetricType.BloodPressure, pref.HealthRecordReminderBloodPressure, "血压"),
(HealthMetricType.HeartRate, pref.HealthRecordReminderHeartRate, "心率"),
(HealthMetricType.Glucose, pref.HealthRecordReminderGlucose, "血糖"),
(HealthMetricType.SpO2, pref.HealthRecordReminderSpO2, "血氧"),
(HealthMetricType.Weight, pref.HealthRecordReminderWeight, "体重"),
};
var missingLabels = missing
.Where(m => m.enabled && !recordedTypes.Contains(m.type))
.Select(m => m.label)
.ToList();
if (missingLabels.Count > 0)
{
var producer = http.RequestServices.GetRequiredService<IUserNotificationProducer>();
var sourceId = Guid.NewGuid();
await producer.EnqueueAsync(userId, sourceId, new NotificationMessage(
Type: "health_record_reminder",
Title: "记录今日健康指标",
Message: $"建议录入:{string.Join("", missingLabels)}",
Severity: "info",
ActionType: "health",
ActionTargetId: null), ct);
}
}
return Results.Ok(new { code = 0, data = ToDto(pref), message = (string?)null });
});
}