polish(ios): 中性化标签与方向胶囊并收紧详情头部间距
- AITag 拆为两类:不传状态色时是中性归类胶囊(tile 底、发丝描边、墨字,可带 10pt 图标), 传状态色时才用 14% 色雾与 30% 描边。颜色只服务状态语义。 - 详情页标签改用 AITag(tag, systemImage: "tag"),与节点卡片同一枚形状;头部 VStack 间距 14 -> 12,读数格 minHeight 62 -> 56,加载完成后不再明显小于下方卡片。 - 消息中心「收件 / 发件」由绿/墨配色改回中性胶囊配 arrow.down.left / arrow.up.right, 绿色重新只表示健康状态。 - 批量标签表在无勾选时给出「先在节点列表勾选要归类的节点」,不再留空白行。 - 文档:0.2.2 增量记录与校验值更新为 0e4ffb74…;版本号后不再带括号, 0.2.0/0.2.1/0.2.2 与 README、现行说明统一改写为「0.2.x 构建 N」。
This commit is contained in:
@@ -105,7 +105,7 @@ struct InstanceDetailView: View {
|
||||
|
||||
private var headerCard: some View {
|
||||
AICard(padding: 16, emphasis: true) {
|
||||
VStack(alignment: .leading, spacing: 14) {
|
||||
VStack(alignment: .leading, spacing: 12) {
|
||||
// 导航栏已经显示实例名,卡片内不再重复,只留地址与状态。
|
||||
HStack(spacing: 8) {
|
||||
Image(systemName: "globe")
|
||||
@@ -128,10 +128,11 @@ struct InstanceDetailView: View {
|
||||
|
||||
moduleAvailability
|
||||
|
||||
if !model.instance.tags.isEmpty {
|
||||
// 与节点卡片同一枚标签形状(同一胶囊、同一图标),两处只有一处能点。
|
||||
if model.instance.tags.isEmpty == false {
|
||||
FlowLayout(spacing: 7) {
|
||||
ForEach(model.instance.tags, id: \.self) { tag in
|
||||
AITag(tag)
|
||||
AITag(tag, systemImage: "tag")
|
||||
}
|
||||
}
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
@@ -490,7 +491,7 @@ struct InstanceDetailView: View {
|
||||
.frame(height: 4)
|
||||
}
|
||||
}
|
||||
.frame(maxWidth: .infinity, minHeight: 62, alignment: .topLeading)
|
||||
.frame(maxWidth: .infinity, minHeight: 56, alignment: .topLeading)
|
||||
.accessibilityElement(children: .combine)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,11 +47,17 @@ struct FleetTagBatchSheet: View {
|
||||
AICard {
|
||||
VStack(alignment: .leading, spacing: 10) {
|
||||
AISectionTitle("已选 \(targets.count) 台", systemImage: "checklist")
|
||||
Text(selectedNames.joined(separator: "、"))
|
||||
.font(.caption)
|
||||
.foregroundStyle(AITheme.muted)
|
||||
.lineLimit(3)
|
||||
.truncationMode(.tail)
|
||||
if targets.isEmpty {
|
||||
Text("先在节点列表勾选要归类的节点。")
|
||||
.font(.caption)
|
||||
.foregroundStyle(AITheme.muted)
|
||||
} else {
|
||||
Text(selectedNames.joined(separator: "、"))
|
||||
.font(.caption)
|
||||
.foregroundStyle(AITheme.muted)
|
||||
.lineLimit(3)
|
||||
.truncationMode(.tail)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -134,7 +134,7 @@ struct MessagesView: View {
|
||||
.layoutPriority(1)
|
||||
AITag(
|
||||
message.direction.label,
|
||||
tint: message.direction == .outgoing ? AITheme.primary : AITheme.success)
|
||||
systemImage: message.direction == .outgoing ? "arrow.up.right" : "arrow.down.left")
|
||||
Spacer(minLength: 8)
|
||||
Text(TimestampText.short(message.timestamp))
|
||||
.font(.caption2.weight(.medium))
|
||||
|
||||
@@ -47,29 +47,42 @@ extension AICard {
|
||||
|
||||
public struct AITag: View {
|
||||
private let text: String
|
||||
private let tint: Color
|
||||
private let tint: Color?
|
||||
private let systemImage: String?
|
||||
|
||||
public init(_ text: String, tint: Color = AITheme.primary) {
|
||||
/// 不传 `tint` 时是中性归类标签(标签、方向这类不带健康含义的信息),
|
||||
/// 传了 `tint` 才是状态标签,用同色色雾与描边。颜色只留给后者。
|
||||
public init(_ text: String, tint: Color? = nil, systemImage: String? = nil) {
|
||||
self.text = text
|
||||
self.tint = tint
|
||||
self.systemImage = systemImage
|
||||
}
|
||||
|
||||
public var body: some View {
|
||||
Text(text)
|
||||
.font(.caption2.weight(.semibold))
|
||||
.foregroundStyle(tint)
|
||||
.lineLimit(1)
|
||||
.truncationMode(.middle)
|
||||
.padding(.horizontal, 10)
|
||||
// 与节点卡片上的标签胶囊同一形状,同一高度;深色底上 10% 色雾几乎看不见,
|
||||
// 所以描边权重必须够,不能让标签在暗色主题里消失。
|
||||
.frame(height: 28)
|
||||
.background(tint.opacity(0.14))
|
||||
.clipShape(Capsule(style: .continuous))
|
||||
.overlay {
|
||||
Capsule(style: .continuous)
|
||||
.strokeBorder(tint.opacity(0.30))
|
||||
let tint = self.tint
|
||||
HStack(spacing: 4) {
|
||||
if let systemImage {
|
||||
Image(systemName: systemImage)
|
||||
.font(.system(size: 10, weight: .semibold))
|
||||
.accessibilityHidden(true)
|
||||
}
|
||||
Text(text)
|
||||
.font(.caption2.weight(.semibold))
|
||||
.lineLimit(1)
|
||||
.truncationMode(.middle)
|
||||
}
|
||||
.padding(.horizontal, 10)
|
||||
// 与节点卡片上的标签胶囊同一形状,同一高度;深色底上 10% 色雾几乎看不见,
|
||||
// 所以描边权重必须够,不能让标签在暗色主题里消失。
|
||||
.frame(height: 28)
|
||||
.foregroundStyle(tint == nil ? AITheme.ink : tint!)
|
||||
.background(tint.map { $0.opacity(0.14) } ?? AITheme.tile)
|
||||
.clipShape(Capsule(style: .continuous))
|
||||
.overlay {
|
||||
Capsule(style: .continuous)
|
||||
.strokeBorder(tint.map { $0.opacity(0.30) } ?? AITheme.tileLine)
|
||||
}
|
||||
.accessibilityLabel(text)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user