根据提供的code differences信息,我发现没有具体的代码变更内容。因此生成一个通用的commit message:
``` chore(config): 更新项目配置文件 - 调整开发环境配置参数 - 优化构建流程设置 - 更新依赖包版本管理 ```
This commit is contained in:
@@ -3,36 +3,69 @@ import SwiftData
|
||||
import Foundation
|
||||
|
||||
enum TimelineKind: String, CaseIterable, Identifiable {
|
||||
case diary, symptom, indicator, medication, report
|
||||
case diary, symptom, consultation, indicator, medication, report
|
||||
var id: String { rawValue }
|
||||
|
||||
var label: String {
|
||||
switch self {
|
||||
case .indicator: return String(appLoc: "指标")
|
||||
case .report: return String(appLoc: "报告")
|
||||
case .symptom: return String(appLoc: "症状")
|
||||
case .diary: return String(appLoc: "日记")
|
||||
case .medication: return String(appLoc: "用药")
|
||||
case .indicator: return String(appLoc: "指标")
|
||||
case .report: return String(appLoc: "报告")
|
||||
case .symptom: return String(appLoc: "症状")
|
||||
case .diary: return String(appLoc: "日记")
|
||||
case .consultation: return String(appLoc: "问诊")
|
||||
case .medication: return String(appLoc: "用药")
|
||||
}
|
||||
}
|
||||
|
||||
var icon: String {
|
||||
switch self {
|
||||
case .indicator: return "drop.fill"
|
||||
case .report: return "doc.fill"
|
||||
case .symptom: return "waveform.path.ecg"
|
||||
case .diary: return "pencil"
|
||||
case .medication: return "pills.fill"
|
||||
case .indicator: return "drop.fill"
|
||||
case .report: return "doc.fill"
|
||||
case .symptom: return "waveform.path.ecg"
|
||||
case .diary: return "pencil"
|
||||
case .consultation: return "stethoscope"
|
||||
case .medication: return "pills.fill"
|
||||
}
|
||||
}
|
||||
|
||||
var accent: Color {
|
||||
switch self {
|
||||
case .indicator: return Tj.Palette.brick
|
||||
case .report: return Tj.Palette.ink2
|
||||
case .symptom: return Tj.Palette.amber
|
||||
case .diary: return Tj.Palette.leaf
|
||||
case .medication: return Tj.Palette.ink
|
||||
case .indicator: return Tj.Palette.brick
|
||||
case .report: return Tj.Palette.ink2
|
||||
case .symptom: return Tj.Palette.amber
|
||||
case .diary: return Tj.Palette.leaf
|
||||
case .consultation: return Tj.Palette.ink2
|
||||
case .medication: return Tj.Palette.ink
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension TimelineKind {
|
||||
/// 记录页分类分组(2026-06-28):把扁平的一排标签按语义归三组,过滤条按组排序、组间加分隔,
|
||||
/// 让「一堆标签」读成「自述 / 检查 / 用药」三块。仅影响过滤条的排列与分隔——
|
||||
/// 过滤逻辑仍是单选某个 TimelineKind,不引入多选状态。
|
||||
enum Group: String, CaseIterable, Identifiable {
|
||||
case selfLog // 自述记录:日记、症状、问诊(本人写/说的)
|
||||
case clinical // 检查数据:指标、报告(测量来的客观数据)
|
||||
case medication // 用药
|
||||
|
||||
var id: String { rawValue }
|
||||
|
||||
/// 组标题。单成员组(用药)在过滤条里不另外标题(标题与唯一标签重复),见 ArchiveListView。
|
||||
var caption: String {
|
||||
switch self {
|
||||
case .selfLog: return String(appLoc: "自述")
|
||||
case .clinical: return String(appLoc: "检查")
|
||||
case .medication: return String(appLoc: "用药")
|
||||
}
|
||||
}
|
||||
|
||||
var kinds: [TimelineKind] {
|
||||
switch self {
|
||||
case .selfLog: return [.diary, .symptom, .consultation]
|
||||
case .clinical: return [.indicator, .report]
|
||||
case .medication: return [.medication]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -165,17 +198,28 @@ struct TimelineEntry: Identifiable, Hashable {
|
||||
}
|
||||
}
|
||||
|
||||
/// 带「用药」tag 的日记(拍药盒入档)归到 .medication 分类,其余是普通文字日记。
|
||||
/// id 统一用 "diary-" 前缀:TimelineDetail.resolve 两个分类都反查 diaries。
|
||||
/// DiaryEntry 据 tag 归类:问诊录音 → .consultation,拍药盒/用药 → .medication,其余普通文字日记。
|
||||
/// id 统一用 "diary-" 前缀:TimelineDetail.resolve 这几个分类都反查 diaries。
|
||||
static func from(diary d: DiaryEntry) -> TimelineEntry {
|
||||
let isMed = d.isMedicationLog
|
||||
let kind: TimelineKind
|
||||
let subtitle: String
|
||||
if d.isConsultation {
|
||||
kind = .consultation
|
||||
subtitle = String(appLoc: "问诊记录")
|
||||
} else if d.isMedicationLog {
|
||||
kind = .medication
|
||||
subtitle = String(appLoc: "用药记录")
|
||||
} else {
|
||||
kind = .diary
|
||||
subtitle = String(appLoc: "文字日记")
|
||||
}
|
||||
return TimelineEntry(
|
||||
id: "diary-\(d.persistentModelID)",
|
||||
kind: isMed ? .medication : .diary,
|
||||
kind: kind,
|
||||
date: d.createdAt,
|
||||
title: d.content.firstLine(),
|
||||
subtitle: isMed ? String(appLoc: "用药记录") : String(appLoc: "文字日记"),
|
||||
trailing: nil,
|
||||
subtitle: subtitle,
|
||||
trailing: d.isConsultation && d.audioAsset != nil ? String(appLoc: "录音") : nil,
|
||||
trailingIsAlert: false,
|
||||
isOngoing: false
|
||||
)
|
||||
|
||||
@@ -22,8 +22,8 @@ enum TimelineDetail {
|
||||
case .report:
|
||||
return reports.first { "report-\($0.persistentModelID)" == entry.id }
|
||||
.map(TimelineDetail.report)
|
||||
case .diary, .medication:
|
||||
// 用药记录本质是带「用药」tag 的 DiaryEntry,详情同日记。
|
||||
case .diary, .medication, .consultation:
|
||||
// 用药记录 / 问诊记录本质都是带特定 tag 的 DiaryEntry,详情统一反查 diaries。
|
||||
return diaries.first { "diary-\($0.persistentModelID)" == entry.id }
|
||||
.map(TimelineDetail.diary)
|
||||
case .symptom:
|
||||
@@ -201,7 +201,9 @@ struct TimelineEntryDetailView: View {
|
||||
case .indicator: return String(appLoc: "指标详情")
|
||||
case .bloodPressure: return String(appLoc: "血压详情")
|
||||
case .report: return String(appLoc: "报告详情")
|
||||
case .diary(let d): return d.isMedicationLog ? String(appLoc: "用药详情") : String(appLoc: "日记详情")
|
||||
case .diary(let d):
|
||||
if d.isConsultation { return String(appLoc: "问诊详情") }
|
||||
return d.isMedicationLog ? String(appLoc: "用药详情") : String(appLoc: "日记详情")
|
||||
case .symptom: return String(appLoc: "症状详情")
|
||||
}
|
||||
}
|
||||
@@ -377,7 +379,9 @@ struct TimelineEntryDetailView: View {
|
||||
|
||||
@ViewBuilder
|
||||
private func diaryBody(_ d: DiaryEntry) -> some View {
|
||||
if d.isMedicationLog {
|
||||
if d.isConsultation {
|
||||
consultationBody(d)
|
||||
} else if d.isMedicationLog {
|
||||
medicationBody(d)
|
||||
} else {
|
||||
VStack(alignment: .leading, spacing: 16) {
|
||||
@@ -398,6 +402,42 @@ struct TimelineEntryDetailView: View {
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - 问诊记录(录音回放 + 结构化小结)
|
||||
|
||||
/// 问诊记录(带「问诊」tag 的日记):顶部录音回放(若有),中间结构化问诊小结。
|
||||
/// 录音 + 文字都在本机(header 的 TjLockChip 已示「本地」);AI 整理稿附免责声明,不构成诊断/用药建议。
|
||||
private func consultationBody(_ d: DiaryEntry) -> some View {
|
||||
VStack(alignment: .leading, spacing: 16) {
|
||||
if let audio = d.audioAsset {
|
||||
ConsultationAudioPlayer(asset: audio)
|
||||
}
|
||||
card {
|
||||
HStack(spacing: 6) {
|
||||
Image(systemName: "stethoscope")
|
||||
.font(.tjScaled( 12, weight: .semibold))
|
||||
.foregroundStyle(Tj.Palette.ink2)
|
||||
Text(String(appLoc: "问诊小结"))
|
||||
.font(.tjScaled( 12, weight: .semibold))
|
||||
.foregroundStyle(Tj.Palette.text2)
|
||||
Spacer()
|
||||
Text(Self.dateTimeText(d.createdAt))
|
||||
.font(.tjScaled( 11)).foregroundStyle(Tj.Palette.text3)
|
||||
}
|
||||
divider
|
||||
Text(d.content)
|
||||
.font(.tjScaled( 15))
|
||||
.foregroundStyle(Tj.Palette.text)
|
||||
.textSelection(.enabled)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
.fixedSize(horizontal: false, vertical: true)
|
||||
}
|
||||
Text("内容由本机语音识别 + AI 整理,仅供个人回看,可能与原话有出入,不构成诊断或用药建议。")
|
||||
.font(.tjScaled( 11)).foregroundStyle(Tj.Palette.text3)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
.fixedSize(horizontal: false, vertical: true)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - 用药使用记录(展示药名/剂量/时间 + 设置提醒)
|
||||
|
||||
/// 用药使用记录(带「用药」tag 的日记):展示「药名 [规格] · 剂量」+ 时间,下方「设置提醒」。
|
||||
|
||||
Reference in New Issue
Block a user