
- 在swift-assistant-style.mdc中添加项目背景、代码结构、命名规范、Swift最佳实践、UI开发、性能、安全性、测试与质量、核心功能、开发流程、App Store指南等详细规则。 - 在yanaApp.swift中将SplashView替换为Splash,简化应用结构。
168 lines
4.3 KiB
Swift
168 lines
4.3 KiB
Swift
import SwiftUI
|
|
|
|
// MARK: - Main ViewModel
|
|
|
|
@MainActor
|
|
class MainViewModel: ObservableObject {
|
|
// MARK: - Published Properties
|
|
@Published var selectedTab: Tab = .feed
|
|
@Published var isLoggedOut: Bool = false
|
|
|
|
// MARK: - Callbacks
|
|
var onLogout: (() -> Void)?
|
|
|
|
// MARK: - Enums
|
|
enum Tab: String, CaseIterable {
|
|
case feed = "feed"
|
|
case me = "me"
|
|
|
|
var title: String {
|
|
switch self {
|
|
case .feed:
|
|
return "Feed"
|
|
case .me:
|
|
return "Me"
|
|
}
|
|
}
|
|
|
|
var iconName: String {
|
|
switch self {
|
|
case .feed:
|
|
return "list.bullet"
|
|
case .me:
|
|
return "person.circle"
|
|
}
|
|
}
|
|
}
|
|
|
|
// MARK: - Public Methods
|
|
func onAppear() {
|
|
debugInfoSync("🚀 MainView onAppear")
|
|
debugInfoSync(" 当前selectedTab: \(selectedTab)")
|
|
}
|
|
|
|
func onTabChanged(_ newTab: Tab) {
|
|
selectedTab = newTab
|
|
debugInfoSync("🔄 MainView selectedTab changed: \(newTab)")
|
|
}
|
|
|
|
func onLogoutTapped() {
|
|
isLoggedOut = true
|
|
onLogout?()
|
|
}
|
|
}
|
|
|
|
// MARK: - Main View
|
|
|
|
struct MainPage: View {
|
|
@StateObject private var viewModel = MainViewModel()
|
|
let onLogout: () -> Void
|
|
|
|
var body: some View {
|
|
NavigationStack {
|
|
GeometryReader { geometry in
|
|
ZStack {
|
|
// 背景图片
|
|
LoginBackgroundView()
|
|
|
|
// 主内容
|
|
mainContentView(geometry: geometry)
|
|
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
|
.padding(.bottom, 80) // 为底部导航栏留出空间
|
|
|
|
// 底部导航栏 - 固定在底部
|
|
VStack {
|
|
Spacer()
|
|
bottomTabView
|
|
}
|
|
}
|
|
}
|
|
}
|
|
.onAppear {
|
|
viewModel.onLogout = onLogout
|
|
viewModel.onAppear()
|
|
}
|
|
.onChange(of: viewModel.isLoggedOut) { _, isLoggedOut in
|
|
if isLoggedOut {
|
|
onLogout()
|
|
}
|
|
}
|
|
}
|
|
|
|
// MARK: - UI Components
|
|
|
|
private func mainContentView(geometry: GeometryProxy) -> some View {
|
|
Group {
|
|
switch viewModel.selectedTab {
|
|
case .feed:
|
|
TempFeedListPage()
|
|
case .me:
|
|
TempMePage()
|
|
}
|
|
}
|
|
}
|
|
|
|
private var bottomTabView: some View {
|
|
HStack(spacing: 0) {
|
|
ForEach(MainViewModel.Tab.allCases, id: \.self) { tab in
|
|
Button(action: {
|
|
viewModel.onTabChanged(tab)
|
|
}) {
|
|
VStack(spacing: 4) {
|
|
Image(systemName: tab.iconName)
|
|
.font(.system(size: 24))
|
|
.foregroundColor(viewModel.selectedTab == tab ? .white : .white.opacity(0.6))
|
|
|
|
Text(tab.title)
|
|
.font(.system(size: 12))
|
|
.foregroundColor(viewModel.selectedTab == tab ? .white : .white.opacity(0.6))
|
|
}
|
|
}
|
|
.frame(maxWidth: .infinity)
|
|
.padding(.vertical, 8)
|
|
}
|
|
}
|
|
.background(
|
|
Rectangle()
|
|
.fill(Color.black.opacity(0.3))
|
|
.background(.ultraThinMaterial)
|
|
)
|
|
}
|
|
}
|
|
|
|
// MARK: - FeedListView (简化版本)
|
|
|
|
struct TempFeedListPage: View {
|
|
var body: some View {
|
|
VStack {
|
|
Text("Feed List")
|
|
.font(.title)
|
|
.foregroundColor(.white)
|
|
|
|
Text("This is a simplified FeedListView")
|
|
.font(.body)
|
|
.foregroundColor(.white.opacity(0.8))
|
|
}
|
|
}
|
|
}
|
|
|
|
// MARK: - MeView (简化版本)
|
|
|
|
struct TempMePage: View {
|
|
var body: some View {
|
|
VStack {
|
|
Text("Me View")
|
|
.font(.title)
|
|
.foregroundColor(.white)
|
|
|
|
Text("This is a simplified MeView")
|
|
.font(.body)
|
|
.foregroundColor(.white.opacity(0.8))
|
|
}
|
|
}
|
|
}
|
|
|
|
#Preview {
|
|
MainPage(onLogout: {})
|
|
}
|