Files
multi-simadmin/apps/ios/Sources/MultiSimAdmin/Features/Device/InstanceDetailView.swift
T

132 lines
4.7 KiB
Swift
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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<String> = ["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)"
}
}