97 lines
3.5 KiB
Swift
97 lines
3.5 KiB
Swift
//
|
||
// 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
|