import Foundation import SwiftData /// 「导出身体档案」单条历史。一次成功生成 = 一条 HealthExport。 /// /// 与 Indicator/Report 等源记录之间用 `[String]` 弱关联(而不是 SwiftData /// 关系),这样源记录被永久删除时,历史导出仍保留为快照。 /// /// 属性写法与项目其他 @Model(Indicator/ChatTurn 等)对齐: /// 不在属性上写 default,所有默认值都在 `init` 里。 @Model final class HealthExport { var prompt: String var content: String var createdAt: Date // 引用回链(§3.3 RAG 引用,W3 再做点击跳转) var referencedIndicatorIDs: [String] var referencedReportIDs: [String] var referencedSymptomIDs: [String] var referencedDiaryIDs: [String] // 意图抽取快照,供「重新生成」复用,不再二次抽意图 var inferredTimeFromDate: Date? var inferredTimeToDate: Date? var inferredIntent: String? /// 意图的中文标签(如「感冒就诊」),供「我的导出」列表 badge 展示;可选,旧库走轻量迁移。 var inferredLabelCN: String? // demo 卖点凭证 /// 模型 tag,如 "Qwen3-1.7B-4bit"。截图能证明本地推理。 var modelTag: String /// 末次 tok/s,对应 demo 卖点 #6 Live Activity 数据。 var decodeRate: Double init(prompt: String = "", content: String = "", createdAt: Date = .now, referencedIndicatorIDs: [String] = [], referencedReportIDs: [String] = [], referencedSymptomIDs: [String] = [], referencedDiaryIDs: [String] = [], inferredTimeFromDate: Date? = nil, inferredTimeToDate: Date? = nil, inferredIntent: String? = nil, inferredLabelCN: String? = nil, modelTag: String = "Qwen3-1.7B-4bit", decodeRate: Double = 0) { self.prompt = prompt self.content = content self.createdAt = createdAt self.referencedIndicatorIDs = referencedIndicatorIDs self.referencedReportIDs = referencedReportIDs self.referencedSymptomIDs = referencedSymptomIDs self.referencedDiaryIDs = referencedDiaryIDs self.inferredTimeFromDate = inferredTimeFromDate self.inferredTimeToDate = inferredTimeToDate self.inferredIntent = inferredIntent self.inferredLabelCN = inferredLabelCN self.modelTag = modelTag self.decodeRate = decodeRate } } extension HealthExport { /// 列表 / strip 显示的 prompt 摘要(≤ 30 字 + ...) var promptPreview: String { let trimmed = prompt.trimmingCharacters(in: .whitespacesAndNewlines) if trimmed.count <= 30 { return trimmed } return trimmed.prefix(30) + "…" } }