import SwiftUI import SwiftData struct MeView: View { @Environment(\.modelContext) private var ctx @Query private var profiles: [UserProfile] @Query private var reminders: [MetricReminder] @Query private var customMetrics: [CustomMonitorMetric] @State private var downloadService = ModelDownloadService.shared private var profile: UserProfile? { profiles.first } private var enabledReminderCount: Int { reminders.filter(\.enabled).count } var body: some View { NavigationStack { ScrollView { VStack(spacing: 12) { profileCard remindersCard customMetricsCard modelManagementCard settingsCard(title: "Face ID 启动锁", detail: "关闭", icon: "faceid") settingsCard(title: "关于", detail: "v0.1 · W2", icon: "info.circle") #if DEBUG DebugAIRunner() .padding(.top, 8) #endif } .padding(.horizontal, 16) .padding(.vertical, 20) } .background(Tj.Palette.sand.ignoresSafeArea()) .navigationTitle("我的") .navigationBarTitleDisplayMode(.large) .onAppear { if profiles.isEmpty { _ = UserProfileStore.loadOrCreate(in: ctx) } downloadService.refreshStates() } } } // MARK: - Cards private var profileCard: some View { NavigationLink { ProfileEditView() } label: { HStack(spacing: 12) { ZStack { Circle() .fill(Tj.Palette.amber.opacity(0.25)) Image(systemName: "person.crop.circle.fill") .font(.system(size: 22)) .foregroundStyle(Tj.Palette.ink) } .frame(width: 44, height: 44) VStack(alignment: .leading, spacing: 2) { Text("个人资料") .font(.system(size: 15, weight: .semibold)) .foregroundStyle(Tj.Palette.text) Text(profileLine) .font(.system(size: 12)) .foregroundStyle(Tj.Palette.text3) .lineLimit(1) } Spacer() Image(systemName: "chevron.right") .font(.system(size: 13, weight: .medium)) .foregroundStyle(Tj.Palette.text3) } .padding(14) .tjCard() } .buttonStyle(.plain) } private var remindersCard: some View { NavigationLink { RemindersListView() } label: { HStack(spacing: 12) { ZStack { Circle() .fill(enabledReminderCount > 0 ? Tj.Palette.amber.opacity(0.25) : Tj.Palette.sand2) Image(systemName: "bell.fill") .font(.system(size: 18)) .foregroundStyle(enabledReminderCount > 0 ? Tj.Palette.ink : Tj.Palette.text2) } .frame(width: 44, height: 44) VStack(alignment: .leading, spacing: 2) { Text("记录提醒") .font(.system(size: 15, weight: .semibold)) .foregroundStyle(Tj.Palette.text) Text(reminderLine) .font(.system(size: 12)) .foregroundStyle(Tj.Palette.text3) .lineLimit(1) } Spacer() Image(systemName: "chevron.right") .font(.system(size: 13, weight: .medium)) .foregroundStyle(Tj.Palette.text3) } .padding(14) .tjCard() } .buttonStyle(.plain) } private var reminderLine: String { if reminders.isEmpty { return "尚未设置" } if enabledReminderCount == 0 { return "全部已关闭(\(reminders.count) 条)" } return "\(enabledReminderCount) 项启用" } private var customMetricsCard: some View { NavigationLink { CustomMetricsListView() } label: { HStack(spacing: 12) { ZStack { Circle() .fill(customMetrics.isEmpty ? Tj.Palette.sand2 : Tj.Palette.leafSoft) Image(systemName: "slider.horizontal.3") .font(.system(size: 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)) .foregroundStyle(Tj.Palette.text) Text(customMetricsLine) .font(.system(size: 12)) .foregroundStyle(Tj.Palette.text3) .lineLimit(1) } Spacer() Image(systemName: "chevron.right") .font(.system(size: 13, weight: .medium)) .foregroundStyle(Tj.Palette.text3) } .padding(14) .tjCard() } .buttonStyle(.plain) } private var customMetricsLine: String { if customMetrics.isEmpty { return "添加你自己的长期监测项" } return "\(customMetrics.count) 项" } private var modelManagementCard: some View { NavigationLink { ModelManagementView() } label: { settingsCard(title: "模型管理", detail: modelDetail, icon: "cpu") } .buttonStyle(.plain) } private var modelDetail: String { let states = downloadService.states if ModelKind.allCases.allSatisfy({ states[$0]?.phase == .ready }) { return "已就绪" } if downloadService.isAnyDownloading { return "下载中…" } let readyCount = ModelKind.allCases.filter { states[$0]?.phase == .ready }.count return readyCount == 0 ? "未下载" : "\(readyCount)/\(ModelKind.allCases.count) 就绪" } private func settingsCard(title: String, detail: String, icon: String) -> some View { HStack(spacing: 12) { ZStack { Circle().fill(Tj.Palette.sand2) Image(systemName: icon) .font(.system(size: 18)) .foregroundStyle(Tj.Palette.text2) } .frame(width: 44, height: 44) Text(title) .font(.system(size: 15, weight: .medium)) .foregroundStyle(Tj.Palette.text) Spacer() Text(detail) .font(.system(size: 12)) .foregroundStyle(Tj.Palette.text3) Image(systemName: "chevron.right") .font(.system(size: 13, weight: .medium)) .foregroundStyle(Tj.Palette.text3) } .padding(14) .tjCard() } private var profileLine: String { guard let p = profile, p.hasAnyBasics else { return "点这里完善你的资料" } return p.summaryLine } } #Preview { MeView() .modelContainer(for: [ UserProfile.self, Indicator.self, Report.self, DiaryEntry.self, Asset.self, ChatTurn.self, Symptom.self, MetricReminder.self, CustomMonitorMetric.self, ], inMemory: true) }