Files
JetsonMediaIOS/Jetson Media/ui/PhotoView.swift
Spasol cb7294d722 Initial Create
基础框架实现
2025-08-16 23:45:52 +08:00

131 lines
4.7 KiB
Swift
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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
}
}