import Foundation @Observable final class HomeViewModel { var recommendedItems: [ContentItem] = [] var latestItems: [ContentItem] = [] var hotMovies: [HotMovieItem] = [] var isLoading = false var error: String? private let cacheKey = "home" var hasData: Bool { !recommendedItems.isEmpty || !latestItems.isEmpty } @MainActor func loadHomeIfNeeded() async { if hasData && !ContentCache.shared.isExpired(key: cacheKey) { return } await loadHome() } @MainActor func loadHome() async { isLoading = true error = nil await withTaskGroup(of: Void.self) { group in group.addTask { await self.loadHomePage() } group.addTask { await self.loadHotMovies() } } if error == nil && hasData { ContentCache.shared.markFresh(key: cacheKey) } isLoading = false } private func loadHomePage() async { do { let html = try await APIClient.shared.fetchHomePage() let sections = try HTMLParser.parseHomeSections(html: html) await MainActor.run { if sections.count > 0 { self.recommendedItems = sections[0] } if sections.count > 1 { self.latestItems = sections[1] } } } catch is CancellationError { } catch let error as URLError where error.code == .cancelled { } catch { await MainActor.run { self.error = error.localizedDescription } } } private func loadHotMovies() async { do { let movies = try await APIClient.shared.fetchHotMovies() await MainActor.run { self.hotMovies = movies } } catch { // 热门 API 失败不影响主页显示 } } }