修复素材上传 OSS 路径并完善调试与表单交互。

对齐 Android material/{scenicId}/0/ 目录结构以修复视频元数据写入失败,补充 API 请求体调试日志、素材拍摄麦克风权限与上传控件点击穿透修复。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-07-13 11:19:58 +08:00
co-authored by Cursor
parent 005349f8e6
commit 7deeedec68
5 changed files with 72 additions and 3 deletions
+42 -2
View File
@@ -340,12 +340,30 @@ final class APIClient {
}
}
/// 在 Debug 环境打印请求信息。
/// 在 Debug 环境打印请求信息(含 GET 查询参数与 POST 请求体,对齐 Android Ktor `LogLevel.BODY`)。
private func logRequest(_ request: URLRequest) {
#if DEBUG
let method = request.httpMethod ?? "REQUEST"
let url = request.url?.absoluteString ?? "<invalid url>"
print("[API][Request] \(method) \(url)")
var lines = ["[API][Request] \(method) \(url)"]
if let queryItems = URLComponents(url: request.url ?? URL(fileURLWithPath: "/"), resolvingAgainstBaseURL: false)?.queryItems,
!queryItems.isEmpty {
let params = queryItems
.map { item in
let value = item.value ?? ""
return "\(item.name)=\(value)"
}
.joined(separator: "&")
lines.append("params: \(params)")
}
let contentType = request.value(forHTTPHeaderField: "Content-Type")
if let body = Self.debugRequestBody(from: request.httpBody, contentType: contentType) {
lines.append("body:\n\(body)")
}
print(lines.joined(separator: "\n"))
#endif
}
@@ -370,6 +388,28 @@ final class APIClient {
}
#if DEBUG
/// 将请求体格式化为便于调试阅读的字符串。
private static func debugRequestBody(from data: Data?, contentType: String?) -> String? {
guard let data, !data.isEmpty else { return nil }
if let contentType, contentType.lowercased().contains("multipart/form-data") {
return "<multipart/form-data: \(data.count) bytes>"
}
if
let object = try? JSONSerialization.jsonObject(with: data),
let prettyData = try? JSONSerialization.data(withJSONObject: object, options: [.prettyPrinted, .sortedKeys]),
let prettyJSON = String(data: prettyData, encoding: .utf8) {
return prettyJSON
}
if let text = String(data: data, encoding: .utf8), !text.isEmpty {
return text.count > 2_000 ? String(text.prefix(2_000)) + "..." : text
}
return "<non-utf8 body: \(data.count) bytes>"
}
/// 将响应体格式化为便于调试阅读的字符串。
private static func debugResponseBody(from data: Data) -> String {
guard !data.isEmpty else { return "<empty response>" }
+2 -1
View File
@@ -314,7 +314,8 @@ enum OSSUploadPolicy {
case "sample":
return "sample/\(currentDate)/\(scenicId)/\(uploadId)_\(safeName)"
case "material":
return "material/\(currentDate)/\(scenicId)/\(uploadId)_\(safeName)"
// Android 素材任务固定 folderId = 0,后端会按此层级解析对象信息并写入视频元数据。
return "material/\(scenicId)/0/\(uploadId)_\(safeName)"
case "punch_point":
let userId = AppStore.shared.session.userId.trimmingCharacters(in: .whitespacesAndNewlines)
let ownerId = userId.isEmpty ? String(scenicId) : userId