- 应用图标改用与 Web favicon 同源的扁平标记,金色 SIM 卡体加三格递增信号,29pt 下仍可读 - 标签统一为胶囊形状,提高深色主题下的描边权重,避免标签在暗色下消失 - 消息卡片与详情分区卡片收紧行距,单屏信息密度明显提升 - 详情头部指标精简为 4 行,数据模块改为单条读数 - 批量选择勾选框移出名称区域,工具栏控件统一为等高 34pt - 分组编辑器改为点选即生效,移除说明文字与常驻禁用按钮
75 lines
2.3 KiB
Swift
75 lines
2.3 KiB
Swift
import Foundation
|
|
|
|
public enum SMSDirection: String, Equatable, Sendable {
|
|
case incoming
|
|
case outgoing
|
|
case unknown
|
|
|
|
public var label: String {
|
|
switch self {
|
|
case .incoming: return "收件"
|
|
case .outgoing: return "发件"
|
|
case .unknown: return "未知"
|
|
}
|
|
}
|
|
}
|
|
|
|
public struct SMSMessage: Equatable, Identifiable, Sendable {
|
|
/// 上游消息 id 只在单个节点内唯一,聚合展示时不能直接当 Identifiable 用。
|
|
public let upstreamID: String
|
|
public let instanceID: UUID
|
|
public let instanceName: String
|
|
public let phoneNumber: String
|
|
public let content: String
|
|
public let direction: SMSDirection
|
|
public let status: String
|
|
public let timestamp: String
|
|
public var id: String { "\(instanceID.uuidString)#\(upstreamID)" }
|
|
|
|
/// 上游 status 是英文原词,列表里直接展示会混进一行英文;未知值仍然原样显示,不做假结论。
|
|
public var statusLabel: String? {
|
|
let key = status.trimmingCharacters(in: .whitespaces).lowercased()
|
|
guard key.isEmpty == false else { return nil }
|
|
switch key {
|
|
case "received", "in", "incoming": return "已接收"
|
|
case "sent": return "已发送"
|
|
case "delivered": return "已送达"
|
|
case "read": return "已读"
|
|
case "failed", "error": return "发送失败"
|
|
case "pending", "queued", "sending": return "发送中"
|
|
default: return status
|
|
}
|
|
}
|
|
|
|
/// 收件的"已接收"和方向标签说的是同一件事,只有发件状态才值得再占一个位置。
|
|
public var deliveryLabel: String? {
|
|
guard direction == .outgoing else { return nil }
|
|
return statusLabel
|
|
}
|
|
|
|
public init(
|
|
upstreamID: String,
|
|
instanceID: UUID,
|
|
instanceName: String,
|
|
phoneNumber: String,
|
|
content: String,
|
|
direction: SMSDirection,
|
|
status: String,
|
|
timestamp: String
|
|
) {
|
|
self.upstreamID = upstreamID
|
|
self.instanceID = instanceID
|
|
self.instanceName = instanceName
|
|
self.phoneNumber = phoneNumber
|
|
self.content = content
|
|
self.direction = direction
|
|
self.status = status
|
|
self.timestamp = timestamp
|
|
}
|
|
}
|
|
|
|
public struct MessagePage: Equatable, Sendable {
|
|
public let messages: [SMSMessage]
|
|
public let total: Int
|
|
}
|