import Foundation /// 打卡状态(对应小程序 STATUSES / android CheckinStatus)。 public enum CheckinStatus: String, CaseIterable, Hashable, Sendable { case normal = "正常" case late = "迟到" case leave = "请假" case absent = "不参加讨论" case earlyLeave = "早退" } /// 小组成员(打卡视角)。 public struct GroupMember: Identifiable, Hashable, Sendable { public let id: String public let name: String public let checkedIn: Bool public let checkinTime: String? public let status: CheckinStatus? public init(id: String, name: String, checkedIn: Bool, checkinTime: String?, status: CheckinStatus?) { self.id = id self.name = name self.checkedIn = checkedIn self.checkinTime = checkinTime self.status = status } } /// 个人打卡历史条目。 public struct PersonalCheckinRecord: Hashable, Sendable { public let date: String public let status: CheckinStatus public let time: String public init(date: String, status: CheckinStatus, time: String) { self.date = date self.status = status self.time = time } } /// 打卡页聚合数据。 public struct CheckinRecord: Hashable, Sendable { public let classDate: String public let weekday: String public let dayNum: Int public let checked: Bool public let status: CheckinStatus? public let groupName: String public let groupMembers: [GroupMember] public let personalHistory: [PersonalCheckinRecord] public init( classDate: String, weekday: String, dayNum: Int, checked: Bool, status: CheckinStatus?, groupName: String, groupMembers: [GroupMember], personalHistory: [PersonalCheckinRecord] ) { self.classDate = classDate self.weekday = weekday self.dayNum = dayNum self.checked = checked self.status = status self.groupName = groupName self.groupMembers = groupMembers self.personalHistory = personalHistory } }