拆分宣传页视图并扩充 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,113 @@
//
// 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