release(ios): 0.2.2 构建 9 修复消息发送遮挡并中性化石墨灰阶
- 消息中心发送入口从被标签栏盖住的底部操作条移到导航栏右侧,发信恢复可用 - 停用态主按钮保留主色淡底与同色描边,与次级按钮拉开层级 - 消息行删除改安静线性图标,去掉一屏红块 - 缺数据读数统一为短横,卡片延迟补空格单位 - 中性灰阶改为严格 R=G=B,浅色主题不再读出冷调;图标石墨底同步去蓝 - 详情页延迟量表改用与卡片同一算法,身份信息值改为右对齐 - 标签加号按钮与输入框同高同圆角
This commit is contained in:
@@ -180,6 +180,9 @@ struct FleetView: View {
|
||||
}
|
||||
|
||||
private extension FleetView {
|
||||
/// 概览读数缺数据时只画一根短横:「不可用」在四列窄格里既占位又容易被读成故障结论。
|
||||
static let noDataText = "—"
|
||||
|
||||
private static let relativeFormatter: RelativeDateTimeFormatter = {
|
||||
let formatter = RelativeDateTimeFormatter()
|
||||
formatter.unitsStyle = .abbreviated
|
||||
@@ -361,7 +364,7 @@ private extension FleetView {
|
||||
)
|
||||
FleetHeadlineStat(
|
||||
title: "异常节点",
|
||||
value: settledCount == 0 ? "--" : "\(abnormalCount)",
|
||||
value: settledCount == 0 ? Self.noDataText : "\(abnormalCount)",
|
||||
detail: abnormalDetail,
|
||||
tint: abnormalTint
|
||||
)
|
||||
@@ -666,7 +669,7 @@ private extension FleetView {
|
||||
private var hasSettledResults: Bool { summaryRows.isEmpty == false && settledCount > 0 }
|
||||
|
||||
private var onlineRateValue: String {
|
||||
guard hasSettledResults else { return "--" }
|
||||
guard hasSettledResults else { return Self.noDataText }
|
||||
return "\(Int((Double(onlineCount) / Double(summaryRows.count) * 100).rounded()))%"
|
||||
}
|
||||
|
||||
@@ -749,10 +752,10 @@ private extension FleetView {
|
||||
|
||||
private var storageSummary: String {
|
||||
let pairs = storagePairs
|
||||
guard pairs.isEmpty == false else { return "不可用" }
|
||||
guard pairs.isEmpty == false else { return Self.noDataText }
|
||||
let used = pairs.map { max(0, $0.total - $0.available) }.reduce(0, +)
|
||||
let total = pairs.map(\.total).reduce(0, +)
|
||||
guard total > 0 else { return "不可用" }
|
||||
guard total > 0 else { return Self.noDataText }
|
||||
return "\(Int((Double(used) / Double(total) * 100).rounded()))% 已用"
|
||||
}
|
||||
|
||||
@@ -777,7 +780,7 @@ private extension FleetView {
|
||||
|
||||
private var trafficSummary: String {
|
||||
let values = summaryRows.compactMap(\.downloadRateBytesPerSecond) + summaryRows.compactMap(\.uploadRateBytesPerSecond)
|
||||
guard values.isEmpty == false else { return "不可用" }
|
||||
guard values.isEmpty == false else { return Self.noDataText }
|
||||
return ByteCountFormatter.string(fromByteCount: Int64(values.reduce(0, +)), countStyle: .decimal) + "/s"
|
||||
}
|
||||
|
||||
@@ -793,7 +796,7 @@ private extension FleetView {
|
||||
}
|
||||
|
||||
private func formatAverage(_ values: [Double], transform: (Double) -> String) -> String {
|
||||
guard values.isEmpty == false else { return "不可用" }
|
||||
guard values.isEmpty == false else { return Self.noDataText }
|
||||
let average = values.reduce(0, +) / Double(values.count)
|
||||
return transform(average)
|
||||
}
|
||||
@@ -927,25 +930,25 @@ private extension FleetView {
|
||||
[
|
||||
FleetGauge(
|
||||
label: "信号",
|
||||
value: row.signalPercent.map { "\($0)%" } ?? "--",
|
||||
value: row.signalPercent.map { "\($0)%" } ?? Self.noDataText,
|
||||
ratio: row.signalPercent.map { Double($0) / 100 },
|
||||
tint: row.signalPercent.flatMap(signalColor) ?? AITheme.muted
|
||||
),
|
||||
FleetGauge(
|
||||
label: "延迟",
|
||||
value: row.latencyMilliseconds.map { "\($0)ms" } ?? "--",
|
||||
value: row.latencyMilliseconds.map { "\($0) ms" } ?? Self.noDataText,
|
||||
ratio: row.latencyMilliseconds.map { max(0, 1 - Double($0) / 1000) },
|
||||
tint: row.latencyMilliseconds.flatMap(latencyColor) ?? AITheme.muted
|
||||
),
|
||||
FleetGauge(
|
||||
label: "CPU",
|
||||
value: row.cpuPercent.map(Self.percentText) ?? "--",
|
||||
value: row.cpuPercent.map(Self.percentText) ?? Self.noDataText,
|
||||
ratio: row.cpuPercent.map { $0 / 100 },
|
||||
tint: row.cpuPercent.flatMap(resourceColor) ?? AITheme.muted
|
||||
),
|
||||
FleetGauge(
|
||||
label: "内存",
|
||||
value: row.memoryPercent.map(Self.percentText) ?? "--",
|
||||
value: row.memoryPercent.map(Self.percentText) ?? Self.noDataText,
|
||||
ratio: row.memoryPercent.map { $0 / 100 },
|
||||
tint: row.memoryPercent.flatMap(resourceColor) ?? AITheme.muted
|
||||
),
|
||||
@@ -993,7 +996,7 @@ private extension FleetView {
|
||||
|
||||
private static func cpuValue(percent: Double?, cores: Int?) -> String? {
|
||||
guard percent != nil || cores != nil else { return nil }
|
||||
let usage = percent.map(Self.percentText) ?? "--"
|
||||
let usage = percent.map(Self.percentText) ?? FleetView.noDataText
|
||||
guard let cores, cores > 0 else { return usage }
|
||||
return "\(usage) · \(cores) 核"
|
||||
}
|
||||
@@ -1296,7 +1299,7 @@ extension FleetView {
|
||||
|
||||
// 没有数据时用弱色占位,读起来不会像"0%"那样的假结论。
|
||||
var isPlaceholder: Bool {
|
||||
value == "--" || value == "不可用" || value == "暂无"
|
||||
value == "--" || value == "—" || value == "不可用" || value == "暂无"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1546,7 +1549,7 @@ extension FleetView {
|
||||
.font(.caption2)
|
||||
.foregroundStyle(AITheme.faint)
|
||||
.lineLimit(1)
|
||||
Text(value ?? "--")
|
||||
Text(value ?? FleetView.noDataText)
|
||||
.font(.footnote.weight(.semibold))
|
||||
.monospacedDigit()
|
||||
.foregroundStyle(isAlert ? tint : AITheme.ink)
|
||||
|
||||
Reference in New Issue
Block a user