import SwiftUI struct SettingsView: View { @StateObject private var model: SettingsViewModel @State private var showsClearDialog = false init(model: SettingsViewModel? = nil) { _model = StateObject(wrappedValue: model ?? DefaultContainer.makeSettingsModel()) } var body: some View { ZStack { AITheme.canvas.ignoresSafeArea() ScrollView { LazyVStack(spacing: 12) { if let errorMessage = model.errorMessage { AICard { Text(errorMessage) .font(.subheadline) .foregroundStyle(AITheme.danger) } } if let notice = model.notice { AICard { Text(notice) .font(.subheadline) .foregroundStyle(AITheme.success) } } runtimeCard storageCard securityCard } .padding(16) } } .navigationTitle("设置") .toolbar { ToolbarItemGroup(placement: .primaryAction) { Button { Task { await model.refresh() } } label: { Label("刷新", systemImage: "arrow.clockwise") } .buttonStyle(AIButtonStyle(kind: .secondary, size: .regular)) .disabled(model.isLoading) } } .refreshable { await model.refresh() } .confirmationDialog( "确认清除运行日志?此操作不可恢复。", isPresented: $showsClearDialog, titleVisibility: .visible ) { Button("清除运行日志", role: .destructive) { Task { await model.clearRuntimeLogs() } } Button("取消", role: .cancel) {} } .task { await model.refresh() } } private var runtimeCard: some View { AICard { VStack(alignment: .leading, spacing: 12) { sectionTitle("应用信息", systemImage: "info.circle") if let runtime = model.runtime { infoRow("版本", "\(runtime.marketingVersion) (\(runtime.buildVersion))") infoRow("设备", runtime.deviceModel) } else { Text("正在读取应用信息…") .font(.subheadline) .foregroundStyle(AITheme.muted) } } } } private var storageCard: some View { AICard { VStack(alignment: .leading, spacing: 12) { sectionTitle("本地数据", systemImage: "externaldrive") infoRow("存储位置", "仅保存在本机应用沙盒") infoRow("当前占用", model.storageLabel) Button { showsClearDialog = true } label: { Label("清除运行日志", systemImage: "trash") } .frame(maxWidth: .infinity) .buttonStyle(AIButtonStyle(kind: .danger, size: .large)) } } } private var securityCard: some View { AICard { VStack(alignment: .leading, spacing: 12) { sectionTitle("安全与登录", systemImage: "lock.shield") infoRow("实例密码", "保存在 iOS 钥匙串") infoRow("登录会话", "仅保存在内存") } } } private func sectionTitle(_ title: String, systemImage: String) -> some View { HStack(spacing: 8) { Image(systemName: systemImage) .foregroundStyle(AITheme.primary) Text(title) .font(.headline.weight(.bold)) Spacer() } } private func infoRow(_ title: String, _ value: String) -> some View { VStack(alignment: .leading, spacing: 4) { Text(title) .font(.caption) .foregroundStyle(AITheme.muted) Text(value) .font(.subheadline) .frame(maxWidth: .infinity, alignment: .leading) .textSelection(.enabled) } } }