// // ScenicPromotionHeroMediaView.swift // suixinkan // // Created by Codex on 2026/7/2. // import SwiftUI /// 宣传页底部主视觉区域,展示当前选中的视频或图片。 struct ScenicPromotionHeroMediaView: View { let selectedMedia: ScenicPromotionMedia? let emptyMode: ScenicPromotionMediaMode let onVideoTap: () -> Void var body: some View { Group { if let media = selectedMedia { Button { if media.mode == .video { onVideoTap() } } label: { ZStack(alignment: .bottomLeading) { ScenicPromotionMediaArtwork(media: media, compact: false, useHeroAsset: true) .frame(maxWidth: .infinity) .frame(height: 220) if media.heroAssetName == nil { LinearGradient( colors: [.clear, .black.opacity(0.56)], startPoint: .center, endPoint: .bottom ) VStack(alignment: .leading, spacing: 8) { if media.mode == .video { Image(systemName: "play.fill") .font(.system(size: 30, weight: .bold)) .foregroundStyle(.white) .frame(width: 64, height: 64) .background(.white.opacity(0.2), in: Circle()) .overlay(Circle().stroke(.white, lineWidth: 3)) .frame(maxWidth: .infinity, alignment: .center) } Label(media.title, systemImage: "mappin.circle.fill") .font(.system(size: 20, weight: .heavy)) .foregroundStyle(.white) Text(media.subtitle) .font(.system(size: 14, weight: .medium)) .foregroundStyle(.white.opacity(0.92)) } .padding(18) } } .clipShape(RoundedRectangle(cornerRadius: 18)) .overlay( RoundedRectangle(cornerRadius: 18) .stroke(.white.opacity(0.86), lineWidth: 1) ) } .buttonStyle(.plain) } else { ScenicPromotionMediaEmptyView(mode: emptyMode) .frame(height: 220) .frame(maxWidth: .infinity) .background(.white.opacity(0.7), in: RoundedRectangle(cornerRadius: 18)) .overlay( RoundedRectangle(cornerRadius: 18) .stroke(.white.opacity(0.85), lineWidth: 1) ) } } } } #if DEBUG #Preview("主视觉") { ScenicPromotionHeroMediaView( selectedMedia: ScenicPromotionPreviewSupport.sampleVideoMedia, emptyMode: .video, onVideoTap: {} ) .padding(.horizontal, 20) } #Preview("主视觉-空") { ScenicPromotionHeroMediaView( selectedMedia: nil, emptyMode: .video, onVideoTap: {} ) .padding(.horizontal, 20) } #endif