// // ScenicPromotionSettingsView.swift // suixinkan // // Created by Codex on 2026/7/2. // import SwiftUI /// 宣传页设置视图,管理排队绑定、素材点与 Mock 上传。 struct ScenicPromotionSettingsView: View { @StateObject private var viewModel = ScenicPromotionSettingsViewModel() @State private var showSelectMaterialPointAlert = false @State private var showSubmitAlert = false @State private var submitMessage = "" var body: some View { ZStack { AppDesign.background.ignoresSafeArea() Group { switch viewModel.pageState { case .idle, .loading: ScenicPromotionSettingsLoadingView() .transition(.opacity.combined(with: .scale(scale: 0.98))) case .empty: ScenicPromotionSettingsFullStateView( icon: "tray", title: "暂无设置数据", message: "当前没有可配置的排队打卡点和素材打卡点", buttonTitle: "重新加载" ) { Task { await viewModel.load() } } .transition(.opacity.combined(with: .move(edge: .bottom))) case .error(let message): ScenicPromotionSettingsFullStateView( icon: "wifi.exclamationmark", title: "加载失败", message: message, buttonTitle: "重试" ) { Task { await viewModel.load() } } .transition(.opacity.combined(with: .move(edge: .bottom))) case .normal: ScenicPromotionSettingsContentView( viewModel: viewModel, onUploadFailed: { showSelectMaterialPointAlert = true } ) .transition(.opacity.combined(with: .move(edge: .bottom))) } } .animation(.easeInOut(duration: 0.24), value: viewModel.pageState) } .navigationTitle("宣传页设置") .navigationBarTitleDisplayMode(.inline) .appNavigationDestination(item: $viewModel.previewMaterial) { material in ScenicPromotionMaterialPreviewView(material: material) } .safeAreaInset(edge: .bottom) { if case .normal = viewModel.pageState { ScenicPromotionSettingsSubmitBarView(onSubmit: handleSubmit) } } .toolbar { ToolbarItem(placement: .navigationBarTrailing) { Menu { ForEach(ScenicPromotionSettingsDemoScenario.allCases) { scenario in Button(scenario.title) { viewModel.applyScenario(scenario) } } } label: { Image(systemName: "ellipsis.circle") .font(.system(size: 18, weight: .semibold)) } .accessibilityLabel("设置页演示状态") } } .alert("请选择素材打卡点", isPresented: $showSelectMaterialPointAlert) { Button("知道了", role: .cancel) {} } message: { Text("视频宣传素材和图片素材上传前,需要先选择素材所属打卡点。") } .alert("提交结果", isPresented: $showSubmitAlert) { Button("知道了", role: .cancel) {} } message: { Text(submitMessage) } .task { await viewModel.loadIfNeeded() } } /// 提交设置并展示 Mock 结果提示。 private func handleSubmit() { if viewModel.submit() { submitMessage = "宣传页设置已保存,当前为 Mock 演示数据。" } else { submitMessage = "请至少绑定一个排队打卡点。" } showSubmitAlert = true } } #if DEBUG #Preview("宣传页设置") { NavigationStack { ScenicPromotionSettingsView() } } #endif