// // ScenicPromotionModels.swift // suixinkan // // Created by Codex on 2026/7/2. // import Foundation import SwiftUI // MARK: - 宣传页页面状态 /// 宣传页主页面加载与展示状态。 enum ScenicPromotionPageState: Equatable { case idle case loading case normal case empty case error(String) } // MARK: - 宣传页演示场景 /// 宣传页产品演示场景,用于验收 Loading / Empty / Error 等状态。 enum ScenicPromotionDemoScenario: String, CaseIterable, Identifiable { case normal case noMedia case noQueue case loading case error case empty var id: String { rawValue } var title: String { switch self { case .normal: return "正常" case .noMedia: return "无媒体" case .noQueue: return "无排队" case .loading: return "加载" case .error: return "异常" case .empty: return "空数据" } } } // MARK: - 宣传页素材类型 /// 宣传页横向素材与主视觉区支持的视频 / 照片模式。 enum ScenicPromotionMediaMode: String, CaseIterable, Identifiable { case video case photo var id: String { rawValue } var title: String { switch self { case .video: return "视频" case .photo: return "照片" } } var iconName: String { switch self { case .video: return "play.circle.fill" case .photo: return "photo.fill" } } } // MARK: - 宣传页设置页状态 /// 宣传页设置页加载与展示状态。 enum ScenicPromotionSettingsPageState: Equatable { case idle case loading case normal case empty case error(String) } // MARK: - 宣传页设置页演示场景 /// 设置页产品演示场景。 enum ScenicPromotionSettingsDemoScenario: String, CaseIterable, Identifiable { case normal case loading case empty case error var id: String { rawValue } var title: String { switch self { case .normal: return "正常" case .loading: return "加载" case .empty: return "空数据" case .error: return "异常" } } } // MARK: - 设置页上传素材类型 /// 设置页中视频宣传素材与图片素材的上传类型。 enum ScenicPromotionUploadKind: String, CaseIterable, Identifiable { case video case image var id: String { rawValue } var title: String { switch self { case .video: return "视频宣传素材" case .image: return "图片素材" } } var shortTitle: String { switch self { case .video: return "视频" case .image: return "图片" } } var uploadTitle: String { switch self { case .video: return "上传视频宣传素材" case .image: return "上传图片素材" } } var emptyTitle: String { switch self { case .video: return "暂无视频宣传素材" case .image: return "暂无图片素材" } } var iconName: String { switch self { case .video: return "video.fill" case .image: return "photo.on.rectangle.angled" } } } // MARK: - 宣传页数据模型 /// 宣传页整块看板数据,后续接接口时可直接替换 Mock 来源。 struct ScenicPromotionBoard: Equatable { let scenicName: String let subtitle: String let qrCodeTitle: String let spots: [ScenicPromotionSpot] } /// 单个打卡点,包含排队数据和该点位的视频 / 图片素材。 struct ScenicPromotionSpot: Identifiable, Equatable { let id: String let name: String let iconName: String let queue: ScenicPromotionQueueInfo? let videos: [ScenicPromotionMedia] let photos: [ScenicPromotionMedia] } /// 当前点位的排队和叫号信息。 struct ScenicPromotionQueueInfo: Equatable { let waitingPeople: Int let estimatedMinutes: Int let averageMinutes: Int let nextNumber: String let currentNumber: String let shootingDuration: String } /// 宣传页横向素材和底部主视觉共用的数据结构。 struct ScenicPromotionMedia: Identifiable, Hashable { let id: String let mode: ScenicPromotionMediaMode let title: String let subtitle: String let duration: String? let palette: [UInt] let assetName: String? let heroAssetName: String? let previewWidth: CGFloat } /// 设置页中的排队打卡点,多选绑定使用。 struct ScenicPromotionQueuePoint: Identifiable, Hashable { let id: String let name: String let areaName: String } /// 设置页中的素材打卡点,上传视频 / 图片前必须先选择。 struct ScenicPromotionMaterialPoint: Identifiable, Hashable { let id: String let name: String let areaName: String } /// 设置页中已上传的 Mock 素材,按素材打卡点分组管理。 struct ScenicPromotionManagedMaterial: Identifiable, Hashable { let id: String let pointID: String let kind: ScenicPromotionUploadKind let title: String let subtitle: String let assetName: String let duration: String? let createdAt: String }