import SwiftUI struct ContentCardView: View { let item: ContentItem #if os(tvOS) private let cardWidth: CGFloat = 250 #else private let cardWidth: CGFloat = 140 #endif private let aspectRatio: CGFloat = 2.0 / 3.0 #if os(tvOS) @Environment(\.isFocused) private var isFocused #endif var body: some View { VStack(alignment: .leading, spacing: 6) { // 海报 ZStack(alignment: .topLeading) { posterImage .frame(width: cardWidth, height: cardWidth / aspectRatio) .clipShape(RoundedRectangle(cornerRadius: 8)) // 评分角标 if let rating = item.rating, rating > 0 { Text(String(format: "%.1f", rating)) .font(.caption2) .fontWeight(.bold) .foregroundStyle(.white) .padding(.horizontal, 6) .padding(.vertical, 2) .background(.orange.gradient, in: RoundedRectangle(cornerRadius: 4)) .padding(6) .frame(maxWidth: .infinity, alignment: .topTrailing) } // 状态徽章 if let badge = item.badges.first { Text(badge) .font(.caption2) .foregroundStyle(.white) .padding(.horizontal, 6) .padding(.vertical, 2) .background(.blue.gradient, in: RoundedRectangle(cornerRadius: 4)) .padding(6) } } // 标题 Text(item.title) .font(.caption) .fontWeight(.medium) .lineLimit(2) .frame(width: cardWidth, alignment: .leading) // 年份 if item.year > 0 { Text("\(String(item.year))") .font(.caption2) .foregroundStyle(.secondary) } } .frame(width: cardWidth) #if os(tvOS) .scaleEffect(isFocused ? 1.1 : 1.0) .shadow(color: isFocused ? .blue.opacity(0.4) : .clear, radius: 10) .animation(.easeInOut(duration: 0.2), value: isFocused) #endif } @ViewBuilder private var posterImage: some View { CachedAsyncImage(url: item.posterURL) { posterPlaceholder } } private var posterPlaceholder: some View { Rectangle() .fill(.quaternary) .overlay { Image(systemName: "film") .font(.title) .foregroundStyle(.tertiary) } } }