210 lines
8.0 KiB
Swift
210 lines
8.0 KiB
Swift
import SwiftUI
|
||
import Foundation
|
||
|
||
// 搜索历史记录管理器(保持不变)
|
||
class SearchHistoryManager {
|
||
static let shared = SearchHistoryManager()
|
||
private let userDefaultsKey = "search_history"
|
||
private let maxHistoryCount = 50
|
||
|
||
var history: [String] {
|
||
UserDefaults.standard.array(forKey: userDefaultsKey) as? [String] ?? []
|
||
}
|
||
|
||
func addHistory(_ query: String) {
|
||
var newHistory = history
|
||
if let index = newHistory.firstIndex(of: query) {
|
||
newHistory.remove(at: index)
|
||
}
|
||
newHistory.insert(query, at: 0)
|
||
if newHistory.count > maxHistoryCount {
|
||
newHistory = Array(newHistory.prefix(maxHistoryCount))
|
||
}
|
||
UserDefaults.standard.set(newHistory, forKey: userDefaultsKey)
|
||
}
|
||
|
||
func removeHistory(_ query: String) {
|
||
var newHistory = history
|
||
if let index = newHistory.firstIndex(of: query) {
|
||
newHistory.remove(at: index)
|
||
UserDefaults.standard.set(newHistory, forKey: userDefaultsKey)
|
||
}
|
||
}
|
||
|
||
func clearAllHistory() {
|
||
UserDefaults.standard.removeObject(forKey: userDefaultsKey)
|
||
}
|
||
}
|
||
|
||
// 修改后的搜索视图(实现数字ID直接导航)
|
||
struct SearchView: View {
|
||
@State private var searchQuery: String = ""
|
||
@State private var searchResults: [AlbumItem] = []
|
||
@State private var isSearching: Bool = false
|
||
@State private var showAlert: Bool = false
|
||
@State private var alertMessage: String = ""
|
||
@State private var searchHistory: [String] = []
|
||
// 添加导航路径状态,用于编程式导航
|
||
@State private var navigationPath = NavigationPath()
|
||
|
||
var body: some View {
|
||
// 使用带路径的NavigationStack以支持编程式导航
|
||
NavigationStack(path: $navigationPath) {
|
||
Form {
|
||
Section(header: Text("Jetson Media")) {
|
||
HStack {
|
||
TextField("输入搜索内容或ID", text: $searchQuery)
|
||
.textFieldStyle(RoundedBorderTextFieldStyle())
|
||
.onChange(of: searchQuery) {
|
||
if $0.isEmpty {
|
||
loadHistory()
|
||
}
|
||
}
|
||
|
||
Button(action: performSearch) {
|
||
if isSearching {
|
||
ProgressView()
|
||
} else {
|
||
Image(systemName: "magnifyingglass")
|
||
}
|
||
}
|
||
.disabled(searchQuery.isEmpty || isSearching)
|
||
}
|
||
}
|
||
|
||
// 搜索历史区域(保持不变)
|
||
if searchQuery.isEmpty && !searchHistory.isEmpty {
|
||
Section(header: HStack {
|
||
Text("搜索历史")
|
||
Spacer()
|
||
Button("清除全部") {
|
||
SearchHistoryManager.shared.clearAllHistory()
|
||
loadHistory()
|
||
}
|
||
.foregroundColor(.red)
|
||
.font(.subheadline)
|
||
}) {
|
||
ForEach(searchHistory, id: \.self) { query in
|
||
HStack {
|
||
Text(query)
|
||
.foregroundColor(.primary)
|
||
.frame(maxWidth: .infinity, alignment: .leading)
|
||
.onTapGesture {
|
||
searchQuery = query
|
||
performSearch()
|
||
}
|
||
|
||
Button(action: {
|
||
SearchHistoryManager.shared.removeHistory(query)
|
||
loadHistory()
|
||
}) {
|
||
Image(systemName: "xmark.circle.fill")
|
||
.foregroundColor(.gray)
|
||
}
|
||
.buttonStyle(PlainButtonStyle())
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// 搜索结果区域(保持不变)
|
||
if !searchResults.isEmpty {
|
||
Section(header: Text("搜索结果")) {
|
||
ForEach(searchResults, id: \.album_id) { item in
|
||
NavigationLink(destination: PhotoView(albumId: item.album_id)) {
|
||
VStack(alignment: .leading) {
|
||
Text(item.title)
|
||
.font(.headline)
|
||
Text("ID: \(item.album_id)")
|
||
.font(.subheadline)
|
||
.foregroundColor(.gray)
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
.navigationTitle("搜索")
|
||
.onAppear {
|
||
loadHistory()
|
||
}
|
||
// 定义导航目的地
|
||
.navigationDestination(for: Int.self) { albumId in
|
||
PhotoView(albumId: String(albumId))
|
||
}
|
||
}
|
||
.alert(isPresented: $showAlert) {
|
||
Alert(title: Text("提示"), message: Text(alertMessage), dismissButton: .default(Text("确定")))
|
||
}
|
||
}
|
||
|
||
private func loadHistory() {
|
||
searchHistory = SearchHistoryManager.shared.history
|
||
}
|
||
|
||
private func performSearch() {
|
||
guard !searchQuery.isEmpty else { return }
|
||
|
||
// 首先检查搜索内容是否为数字
|
||
if let albumId = Int(searchQuery) {
|
||
// 如果是数字,直接导航到对应的ID页面
|
||
SearchHistoryManager.shared.addHistory(searchQuery)
|
||
loadHistory()
|
||
navigationPath.append(albumId)
|
||
return
|
||
}
|
||
|
||
// 如果不是数字,执行正常搜索流程
|
||
SearchHistoryManager.shared.addHistory(searchQuery)
|
||
loadHistory()
|
||
|
||
isSearching = true
|
||
searchResults = []
|
||
|
||
let encodedQuery = searchQuery.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) ?? searchQuery
|
||
let urlString = Config.shared.apiURL(
|
||
path: "\(Config.Path.search)?search_query=\(encodedQuery)&page=1"
|
||
)
|
||
guard let url = URL(string: urlString) else {
|
||
showAlert(message: "无效的URL")
|
||
isSearching = false
|
||
return
|
||
}
|
||
|
||
let task = URLSession.shared.dataTask(with: url) { data, response, error in
|
||
DispatchQueue.main.async {
|
||
self.isSearching = false
|
||
|
||
if let error = error {
|
||
self.showAlert(message: "搜索失败: \(error.localizedDescription)")
|
||
return
|
||
}
|
||
|
||
guard let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode == 200 else {
|
||
self.showAlert(message: "服务器返回错误")
|
||
return
|
||
}
|
||
|
||
guard let data = data else {
|
||
self.showAlert(message: "没有接收到数据")
|
||
return
|
||
}
|
||
|
||
do {
|
||
let decoder = JSONDecoder()
|
||
self.searchResults = try decoder.decode([AlbumItem].self, from: data)
|
||
} catch {
|
||
print("解码错误: \(error)")
|
||
self.showAlert(message: "解析数据失败: \(error.localizedDescription)")
|
||
}
|
||
}
|
||
}
|
||
task.resume()
|
||
}
|
||
|
||
private func showAlert(message: String) {
|
||
alertMessage = message
|
||
showAlert = true
|
||
}
|
||
}
|