import SwiftUI import Foundation // 扩展UserDefaults,用于存储历史记录 extension UserDefaults { // 历史记录存储格式:[album_id: 最近访问时间戳] private var historyRecordsKey: String { "history_records" } var historyRecords: [String: TimeInterval] { get { (object(forKey: historyRecordsKey) as? [String: TimeInterval]) ?? [:] } set { set(newValue, forKey: historyRecordsKey) } } // 添加历史记录(自动去重并更新时间戳) func addHistory(albumId: String) { var records = historyRecords records[albumId] = Date().timeIntervalSince1970 // 更新为当前时间戳 historyRecords = records } // 删除单条历史记录 func removeHistory(albumId: String) { var records = historyRecords records.removeValue(forKey: albumId) historyRecords = records } // 清除所有历史记录 func clearAllHistory() { historyRecords = [:] } } struct ProfileView: View { // 示例用户数据 let username = "Jetson User" // 收藏列表数据 @State private var favoriteAlbums: [AlbumItem] = [] @State private var isLoadingFavorites = false // 历史记录数据 @State private var historyAlbums: [AlbumItem] = [] @State private var isLoadingHistory = false @State private var showHistoryEmpty = false // 错误提示 @State private var showError = false @State private var errorMessage = "" var body: some View { NavigationStack { List { // 用户信息头部 Section { HStack(alignment: .center, spacing: 12) { // 头像 Image(systemName: "person.circle.fill") .resizable() .frame(width: 80, height: 80) .foregroundColor(.blue) // 用户名 VStack(spacing: 4) { Text(username) .font(.headline) } } .padding(.vertical, 20) } // 收藏区域 Section(header: Text("我的收藏") .font(.headline)) { if isLoadingFavorites { HStack { Spacer() ProgressView("加载收藏中...") Spacer() } .padding(.vertical, 20) } else if favoriteAlbums.isEmpty { Text("暂无收藏,快去收藏喜欢的漫画吧~") .foregroundColor(.gray) .padding(.vertical, 20) } else { ForEach(favoriteAlbums) { item in NavigationLink(destination: PhotoView(albumId: item.album_id)) { VStack(alignment: .leading, spacing: 4) { Text(item.title) .font(.subheadline) .lineLimit(2) Text("ID: \(item.album_id)") .font(.caption) .foregroundColor(.gray) } } } .onDelete(perform: removeFromFavorites) } } // 历史记录区域 Section(header: HStack { Text("浏览历史") .font(.headline) Spacer() Button("清除全部") { clearAllHistory() } .foregroundColor(.red) .font(.subheadline) }) { if isLoadingHistory { HStack { Spacer() ProgressView("加载历史中...") Spacer() } .padding(.vertical, 20) } else if historyAlbums.isEmpty { Text("暂无浏览记录") .foregroundColor(.gray) .padding(.vertical, 20) } else { ForEach(historyAlbums) { item in NavigationLink(destination: PhotoView(albumId: item.album_id)) { VStack(alignment: .leading, spacing: 4) { Text(item.title) .font(.subheadline) .lineLimit(2) Text("ID: \(item.album_id)") .font(.caption) .foregroundColor(.gray) } } } .onDelete(perform: removeFromHistory) } } // 设置区域 Section(header: Text("设置")) { Button(action: {}) { HStack { Image(systemName: "gear") .foregroundColor(.gray) Text("设置") } } } } .navigationTitle("我的") .toolbar { EditButton() } .alert(isPresented: $showError) { Alert(title: Text("加载失败"), message: Text(errorMessage), dismissButton: .default(Text("确定"))) } .onAppear { loadFavoriteAlbums() loadHistoryAlbums() // 加载历史记录 } } } // MARK: - 收藏相关方法 private func loadFavoriteAlbums() { let favoriteIds = UserDefaults.standard.favoriteAlbumIds guard !favoriteIds.isEmpty else { favoriteAlbums = [] return } isLoadingFavorites = true favoriteAlbums = [] let group = DispatchGroup() for id in favoriteIds { group.enter() fetchAlbumInfo(albumId: id) { albumItem in if let item = albumItem { favoriteAlbums.append(item) } group.leave() } } group.notify(queue: .main) { favoriteAlbums.sort { $0.album_id > $1.album_id } isLoadingFavorites = false } } private func removeFromFavorites(at offsets: IndexSet) { guard let index = offsets.first else { return } let removedItem = favoriteAlbums[index] favoriteAlbums.remove(at: index) var favorites = UserDefaults.standard.favoriteAlbumIds favorites.removeAll { $0 == removedItem.album_id } UserDefaults.standard.favoriteAlbumIds = favorites } // MARK: - 历史记录相关方法 private func loadHistoryAlbums() { let historyRecords = UserDefaults.standard.historyRecords // 按时间戳排序(最新的在前) let sortedIds = historyRecords.keys.sorted { historyRecords[$0] ?? 0 > historyRecords[$1] ?? 0 } guard !sortedIds.isEmpty else { historyAlbums = [] return } isLoadingHistory = true historyAlbums = [] let group = DispatchGroup() for id in sortedIds { group.enter() fetchAlbumInfo(albumId: id) { albumItem in if let item = albumItem { historyAlbums.append(item) } group.leave() } } group.notify(queue: .main) { isLoadingHistory = false } } private func removeFromHistory(at offsets: IndexSet) { guard let index = offsets.first else { return } let removedItem = historyAlbums[index] historyAlbums.remove(at: index) UserDefaults.standard.removeHistory(albumId: removedItem.album_id) } private func clearAllHistory() { UserDefaults.standard.clearAllHistory() historyAlbums = [] } // MARK: - 通用方法:获取漫画信息 private func fetchAlbumInfo(albumId: String, completion: @escaping (AlbumItem?) -> Void) { let urlString = "http://jm.rbq.college/album/\(albumId)/" guard let url = URL(string: urlString) else { completion(nil) return } URLSession.shared.dataTask(with: url) { data, response, error in if let error = error { DispatchQueue.main.async { showError(message: "加载失败: \(error.localizedDescription)") } completion(nil) return } guard let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode == 200, let data = data else { completion(nil) return } do { let album = try JSONDecoder().decode(Album.self, from: data) let albumItem = AlbumItem(album_id: album.album_id, title: album.name) completion(albumItem) } catch { print("解析数据失败: \(error)") completion(nil) } }.resume() } private func showError(message: String) { errorMessage = message showError = true } }