feat: 健康录入提醒 + 多指标异常 + 用药漏服 + UI 优化
后端 - NotificationPreference 增加健康录入提醒总开关和 5 子项(血压/心率/血糖/血氧/体重) - EF 迁移 AddHealthRecordReminder - 新增 GET/PUT /api/notification-prefs - 新增 HealthRecordReminderService 每天 9 点/12 点扫描未录入用户推送提醒 前端 - 通知偏好对接真实后端 API - 设置页新增「健康录入提醒」总开关+5 子项 - 通知中心右上角加齿轮跳设置页 - 今日健康卡片:4 项异常检测+多项合并;用药只显漏服并按时间窗口区分文案 - 侧边栏头像改圆形白底灰图标,去掉紫色品牌渐变 - 整体背景统一浅灰白 #F6F8FC,去掉浅紫渐变 - 设置页简化(去掉分组/彩色图标方块) - 健康档案保存按钮移到右上角,TextButton 全局默认黑色 - API baseUrl 跟随网络环境
This commit is contained in:
@@ -56,8 +56,77 @@ public static class NotificationEndpoints
|
||||
? Results.Ok(new { code = 0, data = new { deleted = true }, message = (string?)null })
|
||||
: Results.NotFound(new { code = 404, data = (object?)null, message = "通知不存在" });
|
||||
});
|
||||
|
||||
// ── 通知偏好设置 ──
|
||||
var prefsGroup = app.MapGroup("/api/notification-prefs").RequireAuthorization();
|
||||
|
||||
prefsGroup.MapGet("", async (HttpContext http, AppDbContext db, CancellationToken ct) =>
|
||||
{
|
||||
var userId = GetUserId(http);
|
||||
if (userId == Guid.Empty) return Results.Unauthorized();
|
||||
var pref = await db.NotificationPreferences.FirstOrDefaultAsync(p => p.UserId == userId, ct);
|
||||
if (pref == null)
|
||||
{
|
||||
pref = new NotificationPreference { Id = Guid.NewGuid(), UserId = userId };
|
||||
db.NotificationPreferences.Add(pref);
|
||||
await db.SaveChangesAsync(ct);
|
||||
}
|
||||
return Results.Ok(new { code = 0, data = ToDto(pref), message = (string?)null });
|
||||
});
|
||||
|
||||
prefsGroup.MapPut("", async (NotificationPrefsUpdateDto body, HttpContext http, AppDbContext db, CancellationToken ct) =>
|
||||
{
|
||||
var userId = GetUserId(http);
|
||||
if (userId == Guid.Empty) return Results.Unauthorized();
|
||||
var pref = await db.NotificationPreferences.FirstOrDefaultAsync(p => p.UserId == userId, ct);
|
||||
if (pref == null)
|
||||
{
|
||||
pref = new NotificationPreference { Id = Guid.NewGuid(), UserId = userId };
|
||||
db.NotificationPreferences.Add(pref);
|
||||
}
|
||||
if (body.MedicationReminder.HasValue) pref.MedicationReminder = body.MedicationReminder.Value;
|
||||
if (body.FollowUpReminder.HasValue) pref.FollowUpReminder = body.FollowUpReminder.Value;
|
||||
if (body.DoctorReply.HasValue) pref.DoctorReply = body.DoctorReply.Value;
|
||||
if (body.AbnormalAlert.HasValue) pref.AbnormalAlert = body.AbnormalAlert.Value;
|
||||
if (body.HealthRecordReminder.HasValue) pref.HealthRecordReminder = body.HealthRecordReminder.Value;
|
||||
if (body.HealthRecordReminderBloodPressure.HasValue) pref.HealthRecordReminderBloodPressure = body.HealthRecordReminderBloodPressure.Value;
|
||||
if (body.HealthRecordReminderHeartRate.HasValue) pref.HealthRecordReminderHeartRate = body.HealthRecordReminderHeartRate.Value;
|
||||
if (body.HealthRecordReminderGlucose.HasValue) pref.HealthRecordReminderGlucose = body.HealthRecordReminderGlucose.Value;
|
||||
if (body.HealthRecordReminderSpO2.HasValue) pref.HealthRecordReminderSpO2 = body.HealthRecordReminderSpO2.Value;
|
||||
if (body.HealthRecordReminderWeight.HasValue) pref.HealthRecordReminderWeight = body.HealthRecordReminderWeight.Value;
|
||||
pref.UpdatedAt = DateTime.UtcNow;
|
||||
await db.SaveChangesAsync(ct);
|
||||
return Results.Ok(new { code = 0, data = ToDto(pref), message = (string?)null });
|
||||
});
|
||||
}
|
||||
|
||||
private static Guid GetUserId(HttpContext http) =>
|
||||
Guid.TryParse(http.User.FindFirst(ClaimTypes.NameIdentifier)?.Value, out var id) ? id : Guid.Empty;
|
||||
|
||||
private static object ToDto(NotificationPreference pref) => new
|
||||
{
|
||||
medicationReminder = pref.MedicationReminder,
|
||||
followUpReminder = pref.FollowUpReminder,
|
||||
doctorReply = pref.DoctorReply,
|
||||
abnormalAlert = pref.AbnormalAlert,
|
||||
healthRecordReminder = pref.HealthRecordReminder,
|
||||
healthRecordReminderBloodPressure = pref.HealthRecordReminderBloodPressure,
|
||||
healthRecordReminderHeartRate = pref.HealthRecordReminderHeartRate,
|
||||
healthRecordReminderGlucose = pref.HealthRecordReminderGlucose,
|
||||
healthRecordReminderSpO2 = pref.HealthRecordReminderSpO2,
|
||||
healthRecordReminderWeight = pref.HealthRecordReminderWeight,
|
||||
};
|
||||
}
|
||||
|
||||
public sealed record NotificationPrefsUpdateDto(
|
||||
bool? MedicationReminder,
|
||||
bool? FollowUpReminder,
|
||||
bool? DoctorReply,
|
||||
bool? AbnormalAlert,
|
||||
bool? HealthRecordReminder,
|
||||
bool? HealthRecordReminderBloodPressure,
|
||||
bool? HealthRecordReminderHeartRate,
|
||||
bool? HealthRecordReminderGlucose,
|
||||
bool? HealthRecordReminderSpO2,
|
||||
bool? HealthRecordReminderWeight
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user