feat: 更新日志级别管理及底部导航栏组件化
- 在ContentView中根据编译模式初始化日志级别,确保调试信息的灵活性。 - 在APILogger中使用actor封装日志级别,增强并发安全性。 - 新增通用底部Tab栏组件,优化MainPage中的底部导航逻辑,提升代码可维护性。 - 移除冗余的AppRootView和MainView,简化视图结构,提升代码整洁性。
This commit is contained in:
@@ -7,12 +7,18 @@ class APILogger {
|
||||
case basic
|
||||
case detailed
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
static let logLevel: LogLevel = .detailed
|
||||
#else
|
||||
static let logLevel: LogLevel = .none
|
||||
#endif
|
||||
|
||||
// 使用 actor 封装可变全局状态以保证并发安全
|
||||
actor Config {
|
||||
static let shared = Config()
|
||||
#if DEBUG
|
||||
private var level: LogLevel = .detailed
|
||||
#else
|
||||
private var level: LogLevel = .none
|
||||
#endif
|
||||
func get() -> LogLevel { level }
|
||||
func set(_ newLevel: LogLevel) { level = newLevel }
|
||||
}
|
||||
|
||||
private static let logQueue = DispatchQueue(label: "com.yana.api.logger", qos: .utility)
|
||||
|
||||
@@ -90,13 +96,13 @@ class APILogger {
|
||||
body: Data?,
|
||||
finalHeaders: [String: String]? = nil
|
||||
) {
|
||||
#if DEBUG
|
||||
guard logLevel != .none else { return }
|
||||
#else
|
||||
#if !DEBUG
|
||||
return
|
||||
#endif
|
||||
|
||||
logQueue.async {
|
||||
#else
|
||||
Task {
|
||||
let level = await Config.shared.get()
|
||||
guard level != .none else { return }
|
||||
logQueue.async {
|
||||
let timestamp = dateFormatter.string(from: Date())
|
||||
debugInfoSync("\n🚀 [API Request] [\(timestamp)] ==================")
|
||||
debugInfoSync("📍 Endpoint: \(request.endpoint)")
|
||||
@@ -106,13 +112,13 @@ class APILogger {
|
||||
|
||||
// 显示最终的完整 headers(包括默认 headers 和自定义 headers)
|
||||
if let headers = finalHeaders, !headers.isEmpty {
|
||||
if logLevel == .detailed {
|
||||
if level == .detailed {
|
||||
debugInfoSync("📋 Final Headers (包括默认 + 自定义):")
|
||||
let masked = maskHeaders(headers)
|
||||
for (key, value) in masked.sorted(by: { $0.key < $1.key }) {
|
||||
debugInfoSync(" \(key): \(value)")
|
||||
}
|
||||
} else if logLevel == .basic {
|
||||
} else if level == .basic {
|
||||
debugInfoSync("📋 Headers: \(headers.count) 个 headers")
|
||||
// 只显示重要的 headers
|
||||
let importantHeaders = ["Content-Type", "Accept", "User-Agent", "Authorization"]
|
||||
@@ -141,7 +147,7 @@ class APILogger {
|
||||
}
|
||||
}
|
||||
|
||||
if logLevel == .detailed {
|
||||
if level == .detailed {
|
||||
let pretty = maskedBodyString(from: body)
|
||||
debugInfoSync("📦 Request Body: \n\(pretty)")
|
||||
|
||||
@@ -149,7 +155,7 @@ class APILogger {
|
||||
if request.includeBaseParameters {
|
||||
debugInfoSync("📱 Base Parameters: 已自动注入")
|
||||
}
|
||||
} else if logLevel == .basic {
|
||||
} else if level == .basic {
|
||||
let size = body?.count ?? 0
|
||||
debugInfoSync("📦 Request Body: \(formatBytes(size))")
|
||||
|
||||
@@ -159,18 +165,20 @@ class APILogger {
|
||||
}
|
||||
}
|
||||
debugInfoSync("=====================================")
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// MARK: - Response Logging
|
||||
static func logResponse(data: Data, response: HTTPURLResponse, duration: TimeInterval) {
|
||||
#if DEBUG
|
||||
guard logLevel != .none else { return }
|
||||
#else
|
||||
#if !DEBUG
|
||||
return
|
||||
#endif
|
||||
|
||||
logQueue.async {
|
||||
#else
|
||||
Task {
|
||||
let level = await Config.shared.get()
|
||||
guard level != .none else { return }
|
||||
logQueue.async {
|
||||
let timestamp = dateFormatter.string(from: Date())
|
||||
let statusEmoji = response.statusCode < 400 ? "✅" : "❌"
|
||||
debugInfoSync("\n\(statusEmoji) [API Response] [\(timestamp)] ===================")
|
||||
@@ -179,7 +187,7 @@ class APILogger {
|
||||
debugInfoSync("🔗 URL: \(response.url?.absoluteString ?? "Unknown")")
|
||||
debugInfoSync("📏 Data Size: \(formatBytes(data.count))")
|
||||
|
||||
if logLevel == .detailed {
|
||||
if level == .detailed {
|
||||
debugInfoSync("📋 Response Headers:")
|
||||
// 将 headers 转为 [String:String] 后脱敏
|
||||
var headers: [String: String] = [:]
|
||||
@@ -204,18 +212,20 @@ class APILogger {
|
||||
}
|
||||
}
|
||||
debugInfoSync("=====================================")
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// MARK: - Error Logging
|
||||
static func logError(_ error: Error, url: URL?, duration: TimeInterval) {
|
||||
#if DEBUG
|
||||
guard logLevel != .none else { return }
|
||||
#else
|
||||
#if !DEBUG
|
||||
return
|
||||
#endif
|
||||
|
||||
logQueue.async {
|
||||
#else
|
||||
Task {
|
||||
let level = await Config.shared.get()
|
||||
guard level != .none else { return }
|
||||
logQueue.async {
|
||||
let timestamp = dateFormatter.string(from: Date())
|
||||
debugErrorSync("\n❌ [API Error] [\(timestamp)] ======================")
|
||||
debugErrorSync("⏱️ Duration: \(String(format: "%.3f", duration))s")
|
||||
@@ -229,7 +239,7 @@ class APILogger {
|
||||
debugErrorSync("🚨 System Error: \(error.localizedDescription)")
|
||||
}
|
||||
|
||||
if logLevel == .detailed {
|
||||
if level == .detailed {
|
||||
if let urlError = error as? URLError {
|
||||
debugInfoSync("🔍 URLError Code: \(urlError.code.rawValue)")
|
||||
debugInfoSync("🔍 URLError Localized: \(urlError.localizedDescription)")
|
||||
@@ -251,22 +261,26 @@ class APILogger {
|
||||
debugInfoSync("🔍 Full Error: \(error)")
|
||||
}
|
||||
debugErrorSync("=====================================\n")
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// MARK: - Decoded Response Logging
|
||||
static func logDecodedResponse<T>(_ response: T, type: T.Type) {
|
||||
#if DEBUG
|
||||
guard logLevel == .detailed else { return }
|
||||
#else
|
||||
#if !DEBUG
|
||||
return
|
||||
#endif
|
||||
|
||||
logQueue.async {
|
||||
#else
|
||||
Task {
|
||||
let level = await Config.shared.get()
|
||||
guard level == .detailed else { return }
|
||||
logQueue.async {
|
||||
let timestamp = dateFormatter.string(from: Date())
|
||||
debugInfoSync("🎯 [Decoded Response] [\(timestamp)] Type: \(type)")
|
||||
debugInfoSync("=====================================\n")
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// MARK: - Helper Methods
|
||||
@@ -279,18 +293,20 @@ class APILogger {
|
||||
|
||||
// MARK: - Performance Logging
|
||||
static func logPerformanceWarning(duration: TimeInterval, threshold: TimeInterval = 5.0) {
|
||||
#if DEBUG
|
||||
guard logLevel != .none && duration > threshold else { return }
|
||||
#else
|
||||
#if !DEBUG
|
||||
return
|
||||
#endif
|
||||
|
||||
logQueue.async {
|
||||
#else
|
||||
Task {
|
||||
let level = await Config.shared.get()
|
||||
guard level != .none && duration > threshold else { return }
|
||||
logQueue.async {
|
||||
let timestamp = dateFormatter.string(from: Date())
|
||||
debugWarnSync("\n⚠️ [Performance Warning] [\(timestamp)] ============")
|
||||
debugWarnSync("🐌 Request took \(String(format: "%.3f", duration))s (threshold: \(threshold)s)")
|
||||
debugWarnSync("💡 建议:检查网络条件或优化 API 响应")
|
||||
debugWarnSync("================================================\n")
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user