import Foundation import SwiftData @Model final class UserProfile { // —— 核心 5 项 —— var birthYear: Int? // 1990。隐私考虑只存年,不存月日 var biologicalSexRaw: String // "" / "male" / "female" var heightCM: Int? var weightKG: Double? // 体重支持小数(68.5) var bloodTypeRaw: String // "" / "A" / "B" / "AB" / "O" // —— 健康背景 —— var allergies: [String] var chronicConditions: [String] var familyHistory: [String] // —— 当前用药 —— var currentMedications: [String] var updatedAt: Date init(birthYear: Int? = nil, biologicalSexRaw: String = "", heightCM: Int? = nil, weightKG: Double? = nil, bloodTypeRaw: String = "", allergies: [String] = [], chronicConditions: [String] = [], familyHistory: [String] = [], currentMedications: [String] = [], updatedAt: Date = .now) { self.birthYear = birthYear self.biologicalSexRaw = biologicalSexRaw self.heightCM = heightCM self.weightKG = weightKG self.bloodTypeRaw = bloodTypeRaw self.allergies = allergies self.chronicConditions = chronicConditions self.familyHistory = familyHistory self.currentMedications = currentMedications self.updatedAt = updatedAt } } extension UserProfile { enum Sex: String, CaseIterable { case male, female case undisclosed = "" var label: String { switch self { case .male: return "男" case .female: return "女" case .undisclosed: return "不愿透露" } } } var sex: Sex { get { Sex(rawValue: biologicalSexRaw) ?? .undisclosed } set { biologicalSexRaw = newValue.rawValue } } /// 当前年龄。无 birthYear 时返回 nil。基于当前日历年简单相减,不算月日。 var age: Int? { guard let y = birthYear else { return nil } return Calendar.current.component(.year, from: .now) - y } /// 给 ProfileCard 一行预览:"38岁 · 男 · 175cm · 68kg · A型" var summaryLine: String { var parts: [String] = [] if let age { parts.append("\(age)岁") } if sex != .undisclosed { parts.append(sex.label) } if let h = heightCM { parts.append("\(h)cm") } if let w = weightKG { let s = w.truncatingRemainder(dividingBy: 1) == 0 ? String(format: "%.0fkg", w) : String(format: "%.1fkg", w) parts.append(s) } if !bloodTypeRaw.isEmpty { parts.append("\(bloodTypeRaw)型") } return parts.joined(separator: " · ") } /// 资料是否完整到值得显示 summaryLine(否则提示"完善资料") var hasAnyBasics: Bool { birthYear != nil || sex != .undisclosed || heightCM != nil || weightKG != nil || !bloodTypeRaw.isEmpty } /// BMI(kg/m²),需要同时有身高 + 体重才能算 var bmi: Double? { guard let h = heightCM, h > 0, let w = weightKG else { return nil } let m = Double(h) / 100.0 return w / (m * m) } } /// 单例存取:全 App 只允许一份 UserProfile。第一次取自动创建。 enum UserProfileStore { @MainActor static func loadOrCreate(in ctx: ModelContext) -> UserProfile { let descriptor = FetchDescriptor() if let existing = try? ctx.fetch(descriptor).first { return existing } let new = UserProfile() ctx.insert(new) try? ctx.save() return new } }