Files
kangkang/康康/Models/Models.swift
link2026 46b69cf8e1 feat(symptom): add Symptom @Model + start/end sheets + ongoing card
- Symptom @Model with severity 1-5 clamp, isOngoing, duration helpers
- SymptomStartSheet / SymptomEndSheet / OngoingSymptomsCard
- RecordSheet 加 .symptom kind 入口
- RootView 增加 'records' tab + ArchiveListView placeholder
- HomeView 顶部加 OngoingSymptomsCard
- ModelsSchemaTests: 2 个 Symptom 烟测(ongoing predicate + severity clamp)

Note: Symptom 是 CLAUDE.md §10 清单外的新功能,由产品负责人决定加入。
ArchiveListView 仍是 placeholder,真实 C1 实现按计划在 W4。
2026-05-25 23:18:21 +08:00

190 lines
4.5 KiB
Swift

import Foundation
import SwiftData
enum IndicatorStatus: String, Codable, CaseIterable {
case high, low, normal
}
enum ReportType: String, Codable, CaseIterable {
case checkup, lab, imaging, prescription, other
var label: String {
switch self {
case .checkup: return "体检报告"
case .lab: return "化验单"
case .imaging: return "影像报告"
case .prescription: return "处方"
case .other: return "其他"
}
}
}
@Model
final class Indicator {
var name: String
var value: String
var unit: String
var range: String
var statusRaw: String
var note: String?
var capturedAt: Date
var report: Report?
var asset: Asset?
var pinned: Bool = false
init(name: String,
value: String,
unit: String,
range: String,
status: IndicatorStatus,
note: String? = nil,
capturedAt: Date = .now,
report: Report? = nil,
asset: Asset? = nil,
pinned: Bool = false) {
self.name = name
self.value = value
self.unit = unit
self.range = range
self.statusRaw = status.rawValue
self.note = note
self.capturedAt = capturedAt
self.report = report
self.asset = asset
self.pinned = pinned
}
var status: IndicatorStatus {
IndicatorStatus(rawValue: statusRaw) ?? .normal
}
}
@Model
final class Report {
var title: String
var typeRaw: String
var reportDate: Date
var institution: String?
var note: String?
var summary: String?
var pageCount: Int
var createdAt: Date
@Relationship(deleteRule: .cascade, inverse: \Indicator.report)
var indicators: [Indicator] = []
@Relationship(deleteRule: .cascade)
var assets: [Asset] = []
init(title: String,
type: ReportType,
reportDate: Date,
institution: String? = nil,
note: String? = nil,
summary: String? = nil,
pageCount: Int = 1,
createdAt: Date = .now) {
self.title = title
self.typeRaw = type.rawValue
self.reportDate = reportDate
self.institution = institution
self.note = note
self.summary = summary
self.pageCount = pageCount
self.createdAt = createdAt
}
var type: ReportType {
ReportType(rawValue: typeRaw) ?? .other
}
}
@Model
final class DiaryEntry {
var content: String
var createdAt: Date
var tags: [String]
init(content: String, createdAt: Date = .now, tags: [String] = []) {
self.content = content
self.createdAt = createdAt
self.tags = tags
}
}
@Model
final class Asset {
var relativePath: String
var mimeType: String
var bytes: Int
var createdAt: Date
init(relativePath: String,
mimeType: String = "image/jpeg",
bytes: Int = 0,
createdAt: Date = .now) {
self.relativePath = relativePath
self.mimeType = mimeType
self.bytes = bytes
self.createdAt = createdAt
}
}
@Model
final class Symptom {
var name: String
var startedAt: Date
var endedAt: Date?
var note: String?
var severity: Int
var tags: [String]
var createdAt: Date
init(name: String,
startedAt: Date = .now,
endedAt: Date? = nil,
note: String? = nil,
severity: Int = 3,
tags: [String] = [],
createdAt: Date = .now) {
self.name = name
self.startedAt = startedAt
self.endedAt = endedAt
self.note = note
self.severity = max(1, min(5, severity))
self.tags = tags
self.createdAt = createdAt
}
var isOngoing: Bool { endedAt == nil }
var duration: TimeInterval {
(endedAt ?? .now).timeIntervalSince(startedAt)
}
}
@Model
final class ChatTurn {
var question: String
var answer: String
var referencedIndicatorIDs: [String]
var referencedReportIDs: [String]
var createdAt: Date
var decodeRate: Double
init(question: String,
answer: String,
referencedIndicatorIDs: [String] = [],
referencedReportIDs: [String] = [],
createdAt: Date = .now,
decodeRate: Double = 0) {
self.question = question
self.answer = answer
self.referencedIndicatorIDs = referencedIndicatorIDs
self.referencedReportIDs = referencedReportIDs
self.createdAt = createdAt
self.decodeRate = decodeRate
}
}