拆分宣传页视图并扩充 Mock 数据,合作订单支持获客员备注名并修复线索图片网格尺寸。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-07-02 17:43:04 +08:00
parent 1b1e93b9ca
commit 328c4321f4
41 changed files with 2529 additions and 1436 deletions

View File

@ -0,0 +1,96 @@
//
// 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