缺少代码差异信息,无法生成具体的commit message。请提供code differences内容以便分析并生成符合Angular规范的提交信息。

当您提供代码差异后,我将按照以下格式生成:

```
<type>(<scope>): <subject>

<body>
```

其中type会根据更改类型选择(feat、fix、docs、style、refactor等),scope表示影响范围,subject简要描述变更内容,body详细说明修改内容。
This commit is contained in:
link2026
2026-06-07 14:17:18 +08:00
parent 074d99715d
commit 77a4ee1c37
66 changed files with 2676 additions and 548 deletions

View File

@@ -70,12 +70,12 @@ struct AboutView: View {
}
Text("康康 · 本地优先的健康档案 · \(versionText)")
.font(.system(size: 12))
.font(.tjScaled( 12))
.foregroundStyle(Tj.Palette.text3)
.padding(.top, 4)
Text("本 App 仅供健康信息记录与参考,不能替代专业医疗意见。")
.font(.system(size: 11))
.font(.tjScaled( 11))
.foregroundStyle(Tj.Palette.text3)
.multilineTextAlignment(.center)
.fixedSize(horizontal: false, vertical: true)
@@ -98,7 +98,7 @@ struct AboutView: View {
RoundedRectangle(cornerRadius: Tj.Radius.md, style: .continuous)
.fill(Tj.Palette.sand2)
Image(systemName: "heart.text.square.fill")
.font(.system(size: 34))
.font(.tjScaled( 34))
.foregroundStyle(Tj.Palette.brick)
}
.frame(width: 72, height: 72)
@@ -108,7 +108,7 @@ struct AboutView: View {
.foregroundStyle(Tj.Palette.text)
Text("本地优先的个人健康随记")
.font(.system(size: 13))
.font(.tjScaled( 13))
.foregroundStyle(Tj.Palette.text2)
Text(versionText)
@@ -133,10 +133,10 @@ struct AboutView: View {
VStack(alignment: .leading, spacing: 10) {
HStack(spacing: 8) {
Image(systemName: icon)
.font(.system(size: 15, weight: .semibold))
.font(.tjScaled( 15, weight: .semibold))
.foregroundStyle(tint)
Text(title)
.font(.system(size: 16, weight: .semibold))
.font(.tjScaled( 16, weight: .semibold))
.foregroundStyle(Tj.Palette.text)
}
content()
@@ -148,7 +148,7 @@ struct AboutView: View {
@ViewBuilder private func paragraph(_ text: String) -> some View {
Text(text)
.font(.system(size: 14))
.font(.tjScaled( 14))
.foregroundStyle(Tj.Palette.text2)
.lineSpacing(5)
.fixedSize(horizontal: false, vertical: true)
@@ -161,7 +161,7 @@ struct AboutView: View {
.frame(width: 5, height: 5)
.padding(.top, 7)
Text(text)
.font(.system(size: 14))
.font(.tjScaled( 14))
.foregroundStyle(Tj.Palette.text2)
.lineSpacing(5)
.fixedSize(horizontal: false, vertical: true)

View File

@@ -41,7 +41,7 @@ struct CustomMetricsListView: View {
editingTarget = CustomMetricEditTarget(metric: nil)
} label: {
Image(systemName: "plus")
.font(.system(size: 16, weight: .semibold))
.font(.tjScaled( 16, weight: .semibold))
}
}
}
@@ -57,7 +57,7 @@ struct CustomMetricsListView: View {
Image(systemName: "info.circle.fill")
.foregroundStyle(Tj.Palette.text3)
Text("自定义指标会出现在「+ 指标记录 → 长期监测」的 grid 里,可设提醒、进趋势")
.font(.system(size: 12))
.font(.tjScaled( 12))
.foregroundStyle(Tj.Palette.text2)
.fixedSize(horizontal: false, vertical: true)
Spacer(minLength: 0)
@@ -75,7 +75,7 @@ struct CustomMetricsListView: View {
TjPlaceholder(label: String(appLoc: "还没有自定义指标"))
.frame(width: 220, height: 130)
Text("右上角 + 新建一个")
.font(.system(size: 12))
.font(.tjScaled( 12))
.foregroundStyle(Tj.Palette.text3)
Spacer()
}
@@ -88,28 +88,28 @@ struct CustomMetricsListView: View {
ZStack {
Circle().fill(Tj.Palette.leafSoft)
Image(systemName: m.icon)
.font(.system(size: 17, weight: .medium))
.font(.tjScaled( 17, weight: .medium))
.foregroundStyle(Tj.Palette.ink)
}
.frame(width: 40, height: 40)
VStack(alignment: .leading, spacing: 3) {
Text(m.name)
.font(.system(size: 15, weight: .semibold))
.font(.tjScaled( 15, weight: .semibold))
.foregroundStyle(Tj.Palette.text)
.lineLimit(1)
HStack(spacing: 6) {
if !m.unit.isEmpty {
Text(m.unit)
.font(.system(size: 11, design: .monospaced))
.font(.tjScaled( 11, design: .monospaced))
.foregroundStyle(Tj.Palette.text3)
}
if !m.rangeText.isEmpty {
Text("·")
.font(.system(size: 11))
.font(.tjScaled( 11))
.foregroundStyle(Tj.Palette.text3)
Text(m.rangeText)
.font(.system(size: 11, design: .monospaced))
.font(.tjScaled( 11, design: .monospaced))
.foregroundStyle(Tj.Palette.text3)
}
}
@@ -119,10 +119,10 @@ struct CustomMetricsListView: View {
VStack(alignment: .trailing, spacing: 2) {
Text(count == 0 ? String(appLoc: "未使用") : String(appLoc: "\(count)"))
.font(.system(size: 11, weight: count > 0 ? .semibold : .regular))
.font(.tjScaled( 11, weight: count > 0 ? .semibold : .regular))
.foregroundStyle(count > 0 ? Tj.Palette.ink : Tj.Palette.text3)
Image(systemName: "chevron.right")
.font(.system(size: 11, weight: .medium))
.font(.tjScaled( 11, weight: .medium))
.foregroundStyle(Tj.Palette.text3)
}
}

View File

@@ -142,7 +142,7 @@ struct CustomReminderEditSheet: View {
private var skipHint: some View {
Text(String(appLoc: "部分月份无此日,该月将跳过"))
.font(.system(size: 11))
.font(.tjScaled( 11))
.foregroundStyle(Tj.Palette.text3)
}
@@ -169,7 +169,7 @@ struct CustomReminderEditSheet: View {
second: 0, of: pickedTime) ?? pickedTime
} label: {
Text(String(format: "%d:%02d", preset.h, preset.m))
.font(.system(size: 13, weight: on ? .semibold : .regular))
.font(.tjScaled( 13, weight: on ? .semibold : .regular))
.foregroundStyle(on ? Tj.Palette.paper : Tj.Palette.text)
.frame(maxWidth: .infinity, minHeight: 30)
.background(
@@ -203,7 +203,7 @@ struct CustomReminderEditSheet: View {
if on { weekdays.remove(w) } else { weekdays.insert(w) }
} label: {
Text(names[idx])
.font(.system(size: 13, weight: on ? .semibold : .regular))
.font(.tjScaled( 13, weight: on ? .semibold : .regular))
.foregroundStyle(on ? Tj.Palette.paper : Tj.Palette.text)
.frame(maxWidth: .infinity, minHeight: 30)
.background(

View File

@@ -0,0 +1,81 @@
import SwiftUI
/// · / : App
/// (,,)
/// ,便
struct FontSettingsView: View {
@State private var manager = FontScaleManager.shared
/// (,,)
private let sampleBase: CGFloat = 17
var body: some View {
ScrollView {
VStack(spacing: 10) {
ForEach(FontScale.allCases) { option in
row(option)
}
Text("放大后整个 App 的文字立即变大,无需重启。设置会被记住。")
.font(.tjScaled(12))
.foregroundStyle(Tj.Palette.text3)
.frame(maxWidth: .infinity, alignment: .leading)
.padding(.horizontal, 4)
.padding(.top, 6)
}
.padding(.horizontal, 16)
.padding(.vertical, 20)
}
.background(Tj.Palette.sand.ignoresSafeArea())
.navigationTitle("字体大小")
.navigationBarTitleDisplayMode(.inline)
}
private func row(_ option: FontScale) -> some View {
let selected = manager.scale == option
return Button {
manager.set(option)
} label: {
HStack(spacing: 14) {
VStack(alignment: .leading, spacing: 4) {
HStack(spacing: 8) {
Text(option.label)
.font(.system(size: 15, weight: selected ? .semibold : .regular))
.foregroundStyle(Tj.Palette.text)
Text(option.detail)
.font(.system(size: 11))
.foregroundStyle(Tj.Palette.text3)
}
// :,
Text("健康档案 Aa 123")
.font(.system(size: sampleBase * option.multiplier, weight: .medium))
.foregroundStyle(Tj.Palette.text2)
.lineLimit(1)
.minimumScaleFactor(0.5)
}
Spacer(minLength: 8)
ZStack {
Circle()
.strokeBorder(selected ? Tj.Palette.ink : Tj.Palette.line, lineWidth: selected ? 0 : 1.5)
.background(Circle().fill(selected ? Tj.Palette.ink : Color.clear))
.frame(width: 24, height: 24)
if selected {
Image(systemName: "checkmark")
.font(.system(size: 12, weight: .bold))
.foregroundStyle(Tj.Palette.paper)
}
}
}
.padding(14)
.frame(maxWidth: .infinity, alignment: .leading)
.tjCard()
}
.buttonStyle(.plain)
}
}
#Preview {
NavigationStack { FontSettingsView() }
}

View File

@@ -12,7 +12,7 @@ struct LanguageSettingsView: View {
}
Text("切换后整个 App 立即生效,无需重启。")
.font(.system(size: 12))
.font(.tjScaled( 12))
.foregroundStyle(Tj.Palette.text3)
.frame(maxWidth: .infinity, alignment: .leading)
.padding(.horizontal, 4)
@@ -40,14 +40,14 @@ struct LanguageSettingsView: View {
.frame(width: 40, height: 40)
Text(option.displayName)
.font(.system(size: 15, weight: selected ? .semibold : .regular))
.font(.tjScaled( 15, weight: selected ? .semibold : .regular))
.foregroundStyle(Tj.Palette.text)
Spacer()
if selected {
Image(systemName: "checkmark")
.font(.system(size: 14, weight: .semibold))
.font(.tjScaled( 14, weight: .semibold))
.foregroundStyle(Tj.Palette.ink)
}
}
@@ -64,11 +64,11 @@ struct LanguageSettingsView: View {
switch option.pickerIcon {
case .symbol(let name):
Image(systemName: name)
.font(.system(size: 16))
.font(.tjScaled( 16))
.foregroundStyle(fg)
case .glyph(let g):
Text(verbatim: g)
.font(.system(size: 17, weight: .semibold))
.font(.tjScaled( 17, weight: .semibold))
.foregroundStyle(fg)
}
}

View File

@@ -9,6 +9,7 @@ struct MeView: View {
@State private var downloadService = ModelDownloadService.shared
@State private var appLock = AppLock.shared
@State private var lang = LanguageManager.shared
@State private var fontScale = FontScaleManager.shared
// key AppLock.enabledKey
@AppStorage("faceIDLockEnabled") private var lockEnabled = false
@@ -37,6 +38,7 @@ struct MeView: View {
customMetricsCard
modelManagementCard
languageCard
fontScaleCard
faceIDCard
NavigationLink {
AboutView()
@@ -74,23 +76,23 @@ struct MeView: View {
Circle()
.fill(Tj.Palette.amber.opacity(0.25))
Image(systemName: "person.crop.circle.fill")
.font(.system(size: 22))
.font(.tjScaled( 22))
.foregroundStyle(Tj.Palette.ink)
}
.frame(width: 44, height: 44)
VStack(alignment: .leading, spacing: 2) {
Text("个人资料")
.font(.system(size: 15, weight: .semibold))
.font(.tjScaled( 15, weight: .semibold))
.foregroundStyle(Tj.Palette.text)
Text(profileLine)
.font(.system(size: 12))
.font(.tjScaled( 12))
.foregroundStyle(Tj.Palette.text3)
.lineLimit(1)
}
Spacer()
Image(systemName: "chevron.right")
.font(.system(size: 13, weight: .medium))
.font(.tjScaled( 13, weight: .medium))
.foregroundStyle(Tj.Palette.text3)
}
.padding(14)
@@ -108,23 +110,23 @@ struct MeView: View {
Circle()
.fill(customMetrics.isEmpty ? Tj.Palette.sand2 : Tj.Palette.leafSoft)
Image(systemName: "slider.horizontal.3")
.font(.system(size: 18))
.font(.tjScaled( 18))
.foregroundStyle(customMetrics.isEmpty ? Tj.Palette.text2 : Tj.Palette.ink)
}
.frame(width: 44, height: 44)
VStack(alignment: .leading, spacing: 2) {
Text("自定义指标")
.font(.system(size: 15, weight: .semibold))
.font(.tjScaled( 15, weight: .semibold))
.foregroundStyle(Tj.Palette.text)
Text(customMetricsLine)
.font(.system(size: 12))
.font(.tjScaled( 12))
.foregroundStyle(Tj.Palette.text3)
.lineLimit(1)
}
Spacer()
Image(systemName: "chevron.right")
.font(.system(size: 13, weight: .medium))
.font(.tjScaled( 13, weight: .medium))
.foregroundStyle(Tj.Palette.text3)
}
.padding(14)
@@ -166,6 +168,17 @@ struct MeView: View {
.buttonStyle(.plain)
}
private var fontScaleCard: some View {
NavigationLink {
FontSettingsView()
} label: {
settingsCard(title: String(appLoc: "字体大小"),
detail: fontScale.scale.label,
icon: "textformat.size")
}
.buttonStyle(.plain)
}
// MARK: - Face ID ( Toggle )
private var faceIDCard: some View {
@@ -173,17 +186,17 @@ struct MeView: View {
ZStack {
Circle().fill(lockEnabled ? Tj.Palette.amber.opacity(0.25) : Tj.Palette.sand2)
Image(systemName: "faceid")
.font(.system(size: 18))
.font(.tjScaled( 18))
.foregroundStyle(lockEnabled ? Tj.Palette.ink : Tj.Palette.text2)
}
.frame(width: 44, height: 44)
VStack(alignment: .leading, spacing: 2) {
Text("Face ID 启动锁")
.font(.system(size: 15, weight: .medium))
.font(.tjScaled( 15, weight: .medium))
.foregroundStyle(Tj.Palette.text)
Text(faceIDLine)
.font(.system(size: 12))
.font(.tjScaled( 12))
.foregroundStyle(Tj.Palette.text3)
}
Spacer()
@@ -219,20 +232,20 @@ struct MeView: View {
ZStack {
Circle().fill(Tj.Palette.sand2)
Image(systemName: icon)
.font(.system(size: 18))
.font(.tjScaled( 18))
.foregroundStyle(Tj.Palette.text2)
}
.frame(width: 44, height: 44)
Text(title)
.font(.system(size: 15, weight: .medium))
.font(.tjScaled( 15, weight: .medium))
.foregroundStyle(Tj.Palette.text)
Spacer()
Text(detail)
.font(.system(size: 12))
.font(.tjScaled( 12))
.foregroundStyle(Tj.Palette.text3)
Image(systemName: "chevron.right")
.font(.system(size: 13, weight: .medium))
.font(.tjScaled( 13, weight: .medium))
.foregroundStyle(Tj.Palette.text3)
}
.padding(14)

View File

@@ -43,7 +43,7 @@ struct ModelManagementView: View {
if let importError {
Text(importError)
.font(.system(size: 12))
.font(.tjScaled( 12))
.foregroundStyle(Tj.Palette.brick)
.frame(maxWidth: .infinity, alignment: .leading)
}
@@ -86,10 +86,10 @@ struct ModelManagementView: View {
HStack(alignment: .top) {
VStack(alignment: .leading, spacing: 3) {
Text(kind.displayName)
.font(.system(size: 15, weight: .semibold))
.font(.tjScaled( 15, weight: .semibold))
.foregroundStyle(Tj.Palette.text)
Text(subtitle(kind))
.font(.system(size: 12))
.font(.tjScaled( 12))
.foregroundStyle(Tj.Palette.text3)
}
Spacer()
@@ -104,17 +104,17 @@ struct ModelManagementView: View {
Spacer()
Text(speedText(state))
}
.font(.system(size: 11, design: .monospaced))
.font(.tjScaled( 11, design: .monospaced))
.foregroundStyle(Tj.Palette.text3)
} else {
HStack {
Text(formatBytes(ModelManifest.totalBytes(for: kind)))
.font(.system(size: 11, design: .monospaced))
.font(.tjScaled( 11, design: .monospaced))
.foregroundStyle(Tj.Palette.text3)
Spacer()
if case .failed(let message) = state.phase {
Text(message)
.font(.system(size: 11))
.font(.tjScaled( 11))
.foregroundStyle(Tj.Palette.brick)
.lineLimit(1)
}
@@ -156,7 +156,7 @@ struct ModelManagementView: View {
Image(systemName: "checkmark.seal.fill")
Text("两个模型都已就绪")
}
.font(.system(size: 13, weight: .semibold))
.font(.tjScaled( 13, weight: .semibold))
.foregroundStyle(Tj.Palette.leaf)
.frame(maxWidth: .infinity)
.padding(.vertical, 6)
@@ -183,7 +183,7 @@ struct ModelManagementView: View {
VStack(spacing: 8) {
TjLockChip()
Text("100% 本地推理 · 模型仅需下载一次")
.font(.system(size: 11))
.font(.tjScaled( 11))
.foregroundStyle(Tj.Palette.text3)
}
.frame(maxWidth: .infinity)

View File

@@ -37,11 +37,11 @@ struct ModelSelfTestView: View {
VStack(alignment: .leading, spacing: 16) {
VStack(alignment: .leading, spacing: 6) {
Text("测试 PROMPT")
.font(.system(size: 11, weight: .semibold))
.font(.tjScaled( 11, weight: .semibold))
.tracking(0.5)
.foregroundStyle(Tj.Palette.text3)
Text(prompt)
.font(.system(size: 14))
.font(.tjScaled( 14))
.foregroundStyle(Tj.Palette.text)
}
.padding(14)
@@ -50,13 +50,13 @@ struct ModelSelfTestView: View {
HStack {
Text(phase.label)
.font(.system(size: 13, weight: .medium))
.font(.tjScaled( 13, weight: .medium))
.foregroundStyle(statusColor)
.lineLimit(1)
Spacer()
if rate > 0 {
Text(String(format: "%.1f tok/s", rate))
.font(.system(size: 12, design: .monospaced))
.font(.tjScaled( 12, design: .monospaced))
.foregroundStyle(Tj.Palette.text3)
}
}

View File

@@ -74,7 +74,7 @@ struct RemindersListView: View {
private var header: some View {
Text("新建提醒,或在记录指标时开启")
.font(.system(size: 12))
.font(.tjScaled( 12))
.foregroundStyle(Tj.Palette.text3)
.frame(maxWidth: .infinity, alignment: .leading)
}
@@ -89,7 +89,7 @@ struct RemindersListView: View {
private func sectionLabel(_ text: String) -> some View {
Text(text)
.font(.system(size: 12, weight: .semibold))
.font(.tjScaled( 12, weight: .semibold))
.foregroundStyle(Tj.Palette.text3)
.frame(maxWidth: .infinity, alignment: .leading)
.padding(.top, 8)
@@ -146,18 +146,18 @@ private struct CustomReminderRow: View {
Circle()
.fill(reminder.enabled ? Tj.Palette.amber.opacity(0.25) : Tj.Palette.sand2)
Image(systemName: "bell.fill")
.font(.system(size: 16))
.font(.tjScaled( 16))
.foregroundStyle(reminder.enabled ? Tj.Palette.ink : Tj.Palette.text3)
}
.frame(width: 36, height: 36)
VStack(alignment: .leading, spacing: 2) {
Text(reminder.title)
.font(.system(size: 15, weight: .semibold))
.font(.tjScaled( 15, weight: .semibold))
.foregroundStyle(Tj.Palette.text)
.lineLimit(1)
Text("\(reminder.timeLabel) · \(reminder.frequencyLabel)")
.font(.system(size: 12))
.font(.tjScaled( 12))
.foregroundStyle(Tj.Palette.text3)
}
Spacer(minLength: 0)
@@ -173,7 +173,7 @@ private struct CustomReminderRow: View {
// 28×28 , Toggle
Image(systemName: "chevron.right")
.font(.system(size: 12, weight: .semibold))
.font(.tjScaled( 12, weight: .semibold))
.foregroundStyle(Tj.Palette.text3)
.frame(width: 28, height: 28)
}
@@ -223,17 +223,17 @@ private struct ReminderRow: View {
Circle()
.fill(reminder.enabled ? Tj.Palette.amber.opacity(0.25) : Tj.Palette.sand2)
Image(systemName: "bell.fill")
.font(.system(size: 16))
.font(.tjScaled( 16))
.foregroundStyle(reminder.enabled ? Tj.Palette.ink : Tj.Palette.text3)
}
.frame(width: 36, height: 36)
VStack(alignment: .leading, spacing: 2) {
Text(reminder.displayName)
.font(.system(size: 15, weight: .semibold))
.font(.tjScaled( 15, weight: .semibold))
.foregroundStyle(Tj.Palette.text)
Text("\(reminder.timeLabel) · \(reminder.frequencyLabel)")
.font(.system(size: 12))
.font(.tjScaled( 12))
.foregroundStyle(Tj.Palette.text3)
}
@@ -248,7 +248,7 @@ private struct ReminderRow: View {
onTapEdit()
} label: {
Image(systemName: isEditing ? "chevron.up" : "chevron.down")
.font(.system(size: 12, weight: .semibold))
.font(.tjScaled( 12, weight: .semibold))
.foregroundStyle(Tj.Palette.text3)
.frame(width: 28, height: 28)
}
@@ -259,7 +259,7 @@ private struct ReminderRow: View {
private var editingPanel: some View {
VStack(alignment: .leading, spacing: 12) {
HStack {
Text("时间").font(.system(size: 13)).foregroundStyle(Tj.Palette.text2)
Text("时间").font(.tjScaled( 13)).foregroundStyle(Tj.Palette.text2)
Spacer()
DatePicker("", selection: $pickedTime, displayedComponents: .hourAndMinute)
.datePickerStyle(.compact)
@@ -278,7 +278,7 @@ private struct ReminderRow: View {
onDelete()
} label: {
Label("删除提醒", systemImage: "trash")
.font(.system(size: 12, weight: .semibold))
.font(.tjScaled( 12, weight: .semibold))
.foregroundStyle(Tj.Palette.brick)
}
.buttonStyle(.plain)
@@ -310,7 +310,7 @@ private struct ReminderRow: View {
onChange()
} label: {
Text(names[idx])
.font(.system(size: 13,
.font(.tjScaled( 13,
weight: reminder.weekdays.contains(w) ? .semibold : .regular))
.foregroundStyle(reminder.weekdays.contains(w) ? Tj.Palette.paper : Tj.Palette.text)
.frame(maxWidth: .infinity, minHeight: 30)