import SwiftUI struct InstanceDetailView: View { @StateObject private var model: DeviceViewModel @State private var revealsSensitive = false init(instance: Instance, model: DeviceViewModel? = nil) { _model = StateObject(wrappedValue: model ?? DefaultContainer.makeDeviceModel(instance: instance)) } var body: some View { ZStack { AITheme.canvas.ignoresSafeArea() ScrollView { LazyVStack(spacing: 12) { header if let errorMessage = model.errorMessage { AICard { Text(errorMessage) .font(.subheadline) .foregroundStyle(AITheme.warning) } } if let snapshot = model.snapshot { ForEach(snapshot.sections) { section in sectionCard(section) } } } .padding(16) } } .navigationTitle(model.instance.name) .toolbar { ToolbarItem(placement: .primaryAction) { Button { revealsSensitive.toggle() } label: { Label(revealsSensitive ? "隐藏敏感值" : "显示敏感值", systemImage: revealsSensitive ? "eye.slash" : "eye") } .buttonStyle(AIButtonStyle(kind: .secondary, size: .compact)) } } .refreshable { await model.refresh() } .task { await model.refresh() } } private var header: some View { AICard { VStack(alignment: .leading, spacing: 8) { Text("设备详情") .font(.headline) Text(model.instance.origin.absoluteString) .font(.subheadline) .foregroundStyle(AITheme.muted) if model.isLoading { Text("正在读取设备能力…") .font(.subheadline) .foregroundStyle(AITheme.muted) } } } } private func sectionCard(_ section: DeviceSection) -> some View { AICard { VStack(alignment: .leading, spacing: 12) { Text(section.title) .font(.headline) if section.values.isEmpty { Text("此模块当前不可用或未返回数据。") .font(.subheadline) .foregroundStyle(AITheme.muted) } else { ForEach(section.values.sorted(by: { $0.key < $1.key }), id: \.key) { item in HStack(alignment: .top, spacing: 10) { Text(fieldLabel(item.key)) .font(.subheadline) .foregroundStyle(AITheme.muted) .frame(maxWidth: .infinity, alignment: .leading) Text(display(item.key, item.value)) .font(.subheadline) .foregroundStyle(AITheme.ink) .multilineTextAlignment(.trailing) } } } } } } private let fieldLabels: [String: String] = [ "model": "型号", "manufacturer": "制造商", "imei": "IMEI", "revision": "固件版本", "online": "在线", "powered": "基带电源", "present": "SIM 在位", "iccid": "ICCID", "imsi": "IMSI", "phone_numbers": "号码", "sms_center": "短信中心", "operator_name": "运营商", "registration_status": "注册状态", "technology_preference": "网络制式", "signal_strength": "信号强度", "core_count": "核心数", "model_name": "CPU 型号", "state": "连接状态", "latency_ms": "延迟(ms)" ] private let sensitiveKeys: Set = ["imei", "iccid", "imsi", "phone_numbers", "sms_center"] private func fieldLabel(_ key: String) -> String { fieldLabels[key] ?? key.replacingOccurrences(of: "_", with: " ") } private func display(_ key: String, _ value: String) -> String { guard sensitiveKeys.contains(key), !revealsSensitive else { return value } guard let first = value.first, value.count > 6 else { return String(repeating: "•", count: min(value.count, 8)) } let tail = value.suffix(4) return "\(first) •••• \(tail)" } }