131 lines
4.7 KiB
Swift
131 lines
4.7 KiB
Swift
import SwiftUI
|
||
import Combine
|
||
|
||
struct PhotoView: View {
|
||
let albumId: String
|
||
@StateObject private var viewModel: PhotoViewModel
|
||
|
||
init(albumId: String) {
|
||
self.albumId = albumId
|
||
self._viewModel = StateObject(wrappedValue: PhotoViewModel(albumId: albumId))
|
||
}
|
||
|
||
var body: some View {
|
||
ZStack {
|
||
if viewModel.isLoading {
|
||
ProgressView()
|
||
} else if let album = viewModel.album {
|
||
ScrollView {
|
||
VStack(alignment: .leading, spacing: 8) {
|
||
Text(album.name)
|
||
.font(.headline)
|
||
|
||
Text("作者: \(album.authors.joined(separator: ", "))")
|
||
.font(.subheadline)
|
||
|
||
Text("标签: \(album.tags.joined(separator: ", "))")
|
||
.font(.caption)
|
||
.foregroundColor(.gray)
|
||
}
|
||
.padding()
|
||
.frame(maxWidth: .infinity, alignment: .leading)
|
||
.background(Color(.systemBackground))
|
||
|
||
LazyVStack(spacing: 0) { // 去掉图片间距
|
||
ForEach(Array(album.image_urls.enumerated()), id: \.offset) { index, url in
|
||
AsyncImageView(
|
||
url: url,
|
||
nums: album.nums,
|
||
index: index
|
||
)
|
||
.frame(maxWidth: .infinity) // 强制图片填充父视图宽度
|
||
.aspectRatio(contentMode: .fill) // 确保图片填充整个区域
|
||
.clipped() // 防止图片超出边界
|
||
}
|
||
}
|
||
}
|
||
.edgesIgnoringSafeArea(.all) // 让内容填充整个屏幕
|
||
} else if let error = viewModel.error {
|
||
Text("加载失败: \(error.localizedDescription)")
|
||
}
|
||
}
|
||
.alert(isPresented: $viewModel.showAlert) {
|
||
Alert(
|
||
title: Text(viewModel.alertTitle),
|
||
message: Text(viewModel.alertMessage),
|
||
dismissButton: .default(Text("确定"))
|
||
)
|
||
}
|
||
}
|
||
}
|
||
// 其余代码保持不变(PhotoView, PhotoViewModel, Album结构体等)
|
||
class PhotoViewModel: ObservableObject {
|
||
let albumId: String
|
||
|
||
@Published var album: Album?
|
||
@Published var isLoading = false
|
||
@Published var error: Error?
|
||
@Published var scrollPosition: Double = 0
|
||
@Published var showAlert = false
|
||
@Published var alertTitle = ""
|
||
@Published var alertMessage = ""
|
||
|
||
private var cancellables = Set<AnyCancellable>()
|
||
|
||
init(albumId: String) {
|
||
self.albumId = albumId
|
||
loadAlbumData()
|
||
}
|
||
|
||
func loadAlbumData() {
|
||
isLoading = true
|
||
error = nil
|
||
|
||
let urlString = "https://jms.godserver.cn/album/\(albumId)/"
|
||
guard let url = URL(string: urlString) else {
|
||
error = NSError(domain: "无效的URL", code: 0, userInfo: nil)
|
||
isLoading = false
|
||
return
|
||
}
|
||
|
||
print("正在加载相册数据: \(urlString)")
|
||
|
||
URLSession.shared.dataTaskPublisher(for: url)
|
||
.map(\.data)
|
||
.decode(type: Album.self, decoder: JSONDecoder())
|
||
.receive(on: DispatchQueue.main)
|
||
.sink(receiveCompletion: { [weak self] completion in
|
||
self?.isLoading = false
|
||
if case .failure(let error) = completion {
|
||
self?.error = error
|
||
print("相册加载失败: \(error.localizedDescription)")
|
||
}
|
||
}, receiveValue: { [weak self] album in
|
||
self?.album = album
|
||
print("成功加载相册: \(album.name), 包含 \(album.image_urls.count) 张图片")
|
||
})
|
||
.store(in: &cancellables)
|
||
}
|
||
|
||
func showAlert(title: String, message: String) {
|
||
alertTitle = title
|
||
alertMessage = message
|
||
showAlert = true
|
||
}
|
||
}
|
||
struct Album: Codable {
|
||
let album_id: String
|
||
let name: String
|
||
let authors: [String]
|
||
let actors: [String]
|
||
let tags: [String]
|
||
let image_urls: [String]
|
||
let nums: [Int]
|
||
|
||
enum CodingKeys: String, CodingKey {
|
||
case album_id, name, authors, actors, tags
|
||
case image_urls = "image_urls"
|
||
case nums
|
||
}
|
||
}
|