117 lines
4.6 KiB
Swift
117 lines
4.6 KiB
Swift
import SwiftUI
|
|
|
|
struct RankingsView: View {
|
|
@StateObject private var viewModel = RankingsViewModel()
|
|
|
|
var body: some View {
|
|
NavigationStack {
|
|
Group {
|
|
if viewModel.isLoading {
|
|
ProgressView("加载排行榜...")
|
|
} else if let error = viewModel.error {
|
|
VStack {
|
|
Text("加载失败: \(error.localizedDescription)")
|
|
Button("重试") {
|
|
viewModel.loadRankings()
|
|
}
|
|
.padding()
|
|
.background(Color.blue)
|
|
.foregroundColor(.white)
|
|
.cornerRadius(8)
|
|
}
|
|
} else {
|
|
List {
|
|
ForEach(Array(viewModel.rankings.enumerated()), id: \.element.album_id) { index, item in
|
|
HStack(alignment: .center, spacing: 12) {
|
|
// 排名标签
|
|
Text("\(index + 1)")
|
|
.font(.headline)
|
|
.frame(width: 24, height: 24)
|
|
.background(index < 3 ? Color.yellow : Color.gray)
|
|
.foregroundColor(index < 3 ? Color.black : Color.white)
|
|
.cornerRadius(4)
|
|
.padding(.leading, 4)
|
|
|
|
// 内容标题
|
|
NavigationLink(destination: PhotoView(albumId: item.album_id)) {
|
|
VStack(alignment: .leading, spacing: 4) {
|
|
Text(item.title)
|
|
.font(.subheadline)
|
|
.lineLimit(1)
|
|
Text("ID: \(item.album_id)")
|
|
.font(.caption)
|
|
.foregroundColor(.gray)
|
|
}
|
|
}
|
|
|
|
Spacer()
|
|
|
|
// 热度图标
|
|
Image(systemName: "flame.fill")
|
|
.foregroundColor(.orange)
|
|
}
|
|
}
|
|
}
|
|
.refreshable {
|
|
viewModel.loadRankings()
|
|
}
|
|
}
|
|
}
|
|
.navigationTitle("周热度排行")
|
|
}
|
|
}
|
|
}
|
|
|
|
// 排行榜视图模型
|
|
class RankingsViewModel: ObservableObject {
|
|
@Published var rankings: [AlbumItem] = []
|
|
@Published var isLoading = false
|
|
@Published var error: Error?
|
|
|
|
init() {
|
|
loadRankings()
|
|
}
|
|
|
|
func loadRankings() {
|
|
isLoading = true
|
|
error = nil
|
|
|
|
let urlString = Config.shared.apiURL(path: "rankings/week?page=1")
|
|
|
|
guard let url = URL(string: urlString) else {
|
|
error = NSError(domain: "RankingsError", code: 0, userInfo: [NSLocalizedDescriptionKey: "无效的URL"])
|
|
isLoading = false
|
|
return
|
|
}
|
|
|
|
URLSession.shared.dataTask(with: url) { [weak self] data, response, error in
|
|
DispatchQueue.main.async {
|
|
self?.isLoading = false
|
|
|
|
if let error = error {
|
|
self?.error = error
|
|
return
|
|
}
|
|
|
|
guard let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode == 200 else {
|
|
self?.error = NSError(domain: "RankingsError", code: 1, userInfo: [NSLocalizedDescriptionKey: "服务器返回错误"])
|
|
return
|
|
}
|
|
|
|
guard let data = data else {
|
|
self?.error = NSError(domain: "RankingsError", code: 2, userInfo: [NSLocalizedDescriptionKey: "没有接收到数据"])
|
|
return
|
|
}
|
|
|
|
do {
|
|
let decoder = JSONDecoder()
|
|
self?.rankings = try decoder.decode([AlbumItem].self, from: data)
|
|
} catch {
|
|
self?.error = NSError(domain: "RankingsError", code: 3, userInfo: [NSLocalizedDescriptionKey: "解析数据失败: \(error.localizedDescription)"])
|
|
print("排行榜解码错误: \(error)")
|
|
}
|
|
}
|
|
}.resume()
|
|
}
|
|
}
|