namespace Health.WebApi.Endpoints; /// /// 用户与健康档案 API 端点 /// public static class UserEndpoints { public static void MapUserEndpoints(this WebApplication app) { var group = app.MapGroup("/api/user").RequireAuthorization(); // 获取个人信息 group.MapGet("/profile", async (HttpContext http, AppDbContext db, CancellationToken ct) => { var userId = GetUserId(http); var user = await db.Users.Select(u => new { u.Id, u.Phone, u.Role, u.Name, u.Gender, BirthDate = u.BirthDate != null ? u.BirthDate.Value.ToString("yyyy-MM-dd") : null, u.AvatarUrl }).FirstOrDefaultAsync(u => u.Id == userId, ct); return Results.Ok(new { code = 0, data = user, message = (string?)null }); }); // 修改资料 group.MapPut("/profile", async (UpdateProfileRequest req, HttpContext http, AppDbContext db, CancellationToken ct) => { var userId = GetUserId(http); var user = await db.Users.FindAsync([userId], ct); if (user == null) return Results.Ok(new { code = 40004, message = "用户不存在" }); user.Name = req.Name ?? user.Name; user.Gender = req.Gender ?? user.Gender; if (DateOnly.TryParse(req.BirthDate, out var bd)) user.BirthDate = bd; user.UpdatedAt = DateTime.UtcNow; await db.SaveChangesAsync(ct); return Results.Ok(new { code = 0, data = new { success = true }, message = (string?)null }); }); // 获取健康档案 group.MapGet("/health-archive", async (HttpContext http, AppDbContext db, CancellationToken ct) => { var userId = GetUserId(http); var archive = await db.HealthArchives.FirstOrDefaultAsync(a => a.UserId == userId, ct); return Results.Ok(new { code = 0, data = archive, message = (string?)null }); }); // 更新健康档案 group.MapPut("/health-archive", async (UpdateArchiveRequest req, HttpContext http, AppDbContext db, CancellationToken ct) => { var userId = GetUserId(http); var archive = await db.HealthArchives.FirstOrDefaultAsync(a => a.UserId == userId, ct); if (archive == null) { archive = new HealthArchive { Id = Guid.NewGuid(), UserId = userId }; db.HealthArchives.Add(archive); } archive.Diagnosis = req.Diagnosis ?? archive.Diagnosis; archive.SurgeryType = req.SurgeryType ?? archive.SurgeryType; if (DateOnly.TryParse(req.SurgeryDate, out var sd)) archive.SurgeryDate = sd; if (req.Allergies != null) archive.Allergies = req.Allergies; if (req.DietRestrictions != null) archive.DietRestrictions = req.DietRestrictions; if (req.ChronicDiseases != null) archive.ChronicDiseases = req.ChronicDiseases; archive.FamilyHistory = req.FamilyHistory ?? archive.FamilyHistory; archive.UpdatedAt = DateTime.UtcNow; await db.SaveChangesAsync(ct); return Results.Ok(new { code = 0, data = new { success = true }, message = (string?)null }); }); // 注销账号 group.MapDelete("/account", async (HttpContext http, AppDbContext db, CancellationToken ct) => { var userId = GetUserId(http); // 医生:清除Doctor关联 var profile = await db.DoctorProfiles.FirstOrDefaultAsync(p => p.UserId == userId, ct); if (profile?.DoctorId != null) { await db.Users.Where(u => u.DoctorId == profile!.DoctorId).ExecuteUpdateAsync(u => u.SetProperty(x => x.DoctorId, (Guid?)null), ct); await db.Doctors.Where(d => d.Id == profile.DoctorId).ExecuteDeleteAsync(ct); } // 删除所有关联数据 await db.HealthRecords.Where(r => r.UserId == userId).ExecuteDeleteAsync(ct); await db.MedicationLogs.Where(l => l.UserId == userId).ExecuteDeleteAsync(ct); await db.Medications.Where(m => m.UserId == userId).ExecuteDeleteAsync(ct); await db.DietFoodItems.Where(i => i.DietRecord!.UserId == userId).ExecuteDeleteAsync(ct); await db.DietRecords.Where(d => d.UserId == userId).ExecuteDeleteAsync(ct); await db.ExercisePlanItems.Where(i => i.Plan!.UserId == userId).ExecuteDeleteAsync(ct); await db.ExercisePlans.Where(p => p.UserId == userId).ExecuteDeleteAsync(ct); await db.Reports.Where(r => r.UserId == userId).ExecuteDeleteAsync(ct); await db.ConversationMessages.Where(m => m.Conversation!.UserId == userId).ExecuteDeleteAsync(ct); await db.Conversations.Where(c => c.UserId == userId).ExecuteDeleteAsync(ct); await db.ConsultationMessages.Where(m => m.Consultation!.UserId == userId).ExecuteDeleteAsync(ct); await db.Consultations.Where(c => c.UserId == userId).ExecuteDeleteAsync(ct); await db.FollowUps.Where(f => f.UserId == userId).ExecuteDeleteAsync(ct); await db.RefreshTokens.Where(t => t.UserId == userId).ExecuteDeleteAsync(ct); await db.DeviceTokens.Where(t => t.UserId == userId).ExecuteDeleteAsync(ct); await db.NotificationPreferences.Where(p => p.UserId == userId).ExecuteDeleteAsync(ct); await db.HealthArchives.Where(a => a.UserId == userId).ExecuteDeleteAsync(ct); await db.DoctorProfiles.Where(p => p.UserId == userId).ExecuteDeleteAsync(ct); await db.Users.Where(u => u.Id == userId).ExecuteDeleteAsync(ct); return Results.Ok(new { code = 0, data = new { success = true }, message = (string?)null }); }); } private static Guid GetUserId(HttpContext http) => Guid.TryParse(http.User.FindFirst(System.Security.Claims.ClaimTypes.NameIdentifier)?.Value, out var id) ? id : Guid.Empty; } public sealed record UpdateProfileRequest(string? Name, string? Gender, string? BirthDate); public sealed record UpdateArchiveRequest( string? Diagnosis, string? SurgeryType, string? SurgeryDate, List? Allergies, List? DietRestrictions, List? ChronicDiseases, string? FamilyHistory);