feat: 上传素材
This commit is contained in:
parent
6a05bd0dc2
commit
4b11885d21
@ -507,16 +507,49 @@ struct PhotoPicker: UIViewControllerRepresentable {
|
|||||||
case .success(let results):
|
case .success(let results):
|
||||||
uploadResults[index] = results
|
uploadResults[index] = results
|
||||||
|
|
||||||
// Upload file info to backend
|
// 使用 NetworkService 上传文件信息
|
||||||
MaterialService.shared.uploadMaterialInfo(
|
let parameters: [String: Any] = [
|
||||||
fileId: results.original.fileId,
|
"file_id": results.original.fileId,
|
||||||
previewFileId: results.compressed.fileId
|
"preview_file_id": results.compressed.fileId
|
||||||
) { success, errorMessage in
|
]
|
||||||
if success {
|
|
||||||
print("✅ 文件信息上传成功")
|
// 将参数包装在数组中
|
||||||
} else if let errorMessage = errorMessage {
|
let requestBody: [[String: Any]] = [parameters]
|
||||||
print("❌ 文件信息上传失败: \(errorMessage)")
|
|
||||||
|
// 定义响应模型
|
||||||
|
struct MaterialResponse: Decodable {
|
||||||
|
let success: Bool
|
||||||
|
let message: String?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 直接使用 URLSession 发送请求,确保数据格式正确
|
||||||
|
do {
|
||||||
|
let jsonData = try JSONSerialization.data(withJSONObject: requestBody)
|
||||||
|
var request = URLRequest(url: URL(string: "\(APIConfig.baseURL)/material")!)
|
||||||
|
request.httpMethod = "POST"
|
||||||
|
request.allHTTPHeaderFields = APIConfig.authHeaders
|
||||||
|
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
|
||||||
|
request.httpBody = jsonData
|
||||||
|
|
||||||
|
let task = URLSession.shared.dataTask(with: request) { data, response, error in
|
||||||
|
if let error = error {
|
||||||
|
print("❌ 文件信息上传失败: \(error.localizedDescription)")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if let httpResponse = response as? HTTPURLResponse {
|
||||||
|
if (200...299).contains(httpResponse.statusCode) {
|
||||||
|
print("✅ 文件信息上传成功")
|
||||||
|
} else {
|
||||||
|
let statusCode = httpResponse.statusCode
|
||||||
|
let errorMessage = String(data: data ?? Data(), encoding: .utf8) ?? ""
|
||||||
|
print("❌ 服务器返回错误状态码: \(statusCode), 响应: \(errorMessage)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
task.resume()
|
||||||
|
} catch {
|
||||||
|
print("❌ 请求数据序列化失败: \(error.localizedDescription)")
|
||||||
}
|
}
|
||||||
|
|
||||||
case .failure(let error):
|
case .failure(let error):
|
||||||
|
|||||||
@ -17,10 +17,12 @@ class MaterialService {
|
|||||||
previewFileId: String,
|
previewFileId: String,
|
||||||
completion: @escaping (Bool, String?) -> Void) {
|
completion: @escaping (Bool, String?) -> Void) {
|
||||||
|
|
||||||
let materialData: [[String: String]] = [[
|
let materialData: [String: Any] = [
|
||||||
|
"material": [
|
||||||
"file_id": fileId,
|
"file_id": fileId,
|
||||||
"preview_file_id": previewFileId
|
"preview_file_id": previewFileId
|
||||||
]]
|
]
|
||||||
|
]
|
||||||
|
|
||||||
guard let url = URL(string: "\(APIConfig.baseURL)/material") else {
|
guard let url = URL(string: "\(APIConfig.baseURL)/material") else {
|
||||||
completion(false, "无效的URL")
|
completion(false, "无效的URL")
|
||||||
@ -46,7 +48,8 @@ class MaterialService {
|
|||||||
completion(true, nil)
|
completion(true, nil)
|
||||||
} else {
|
} else {
|
||||||
let statusCode = httpResponse.statusCode
|
let statusCode = httpResponse.statusCode
|
||||||
completion(false, "服务器返回错误状态码: \(statusCode)")
|
let errorMessage = String(data: data ?? Data(), encoding: .utf8) ?? ""
|
||||||
|
completion(false, "服务器返回错误状态码: \(statusCode), 响应: \(errorMessage)")
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
completion(false, "无效的服务器响应")
|
completion(false, "无效的服务器响应")
|
||||||
|
|||||||
@ -10,7 +10,6 @@ struct UserInfo: View {
|
|||||||
@State private var darkModeEnabled = false
|
@State private var darkModeEnabled = false
|
||||||
@State private var showLogoutAlert = false
|
@State private var showLogoutAlert = false
|
||||||
@State private var avatarImage: UIImage? // Add this line
|
@State private var avatarImage: UIImage? // Add this line
|
||||||
@State private var name: String = ""
|
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
VStack(spacing: 0) {
|
VStack(spacing: 0) {
|
||||||
@ -40,49 +39,53 @@ struct UserInfo: View {
|
|||||||
.font(Typography.font(for: .title))
|
.font(Typography.font(for: .title))
|
||||||
.frame(maxWidth: .infinity, alignment: .center)
|
.frame(maxWidth: .infinity, alignment: .center)
|
||||||
|
|
||||||
// Avatar section
|
// Avatar
|
||||||
VStack {
|
ZStack {
|
||||||
Text("your name")
|
// Show either the SVG or the uploaded image
|
||||||
.font(.headline)
|
if let avatarImage = avatarImage {
|
||||||
.padding(.bottom, 10)
|
Image(uiImage: avatarImage)
|
||||||
|
|
||||||
// Avatar image or placeholder
|
|
||||||
Circle()
|
|
||||||
.fill(Color.gray.opacity(0.3))
|
|
||||||
.frame(width: 100, height: 100)
|
|
||||||
.overlay(
|
|
||||||
Image(systemName: "person.fill")
|
|
||||||
.resizable()
|
.resizable()
|
||||||
.scaledToFit()
|
.scaledToFill()
|
||||||
.foregroundColor(.white)
|
.frame(width: 200, height: 200)
|
||||||
.padding(30)
|
.clipShape(Circle())
|
||||||
)
|
} else {
|
||||||
|
SVGImage(svgName: "Avatar")
|
||||||
|
.frame(width: 200, height: 200)
|
||||||
}
|
}
|
||||||
.padding(.top, 30)
|
|
||||||
|
|
||||||
// Name input field
|
// Make sure the AvatarUploader is on top and covers the entire area
|
||||||
TextField("Enter your name", text: $name)
|
AvatarUploader(selectedImage: $avatarImage, size: 200)
|
||||||
.textFieldStyle(RoundedBorderTextFieldStyle())
|
.contentShape(Rectangle()) // This makes the entire area tappable
|
||||||
.padding(.horizontal, 40)
|
}
|
||||||
.padding(.top, 20)
|
.frame(width: 200, height: 200)
|
||||||
|
.padding(.vertical, 20)
|
||||||
|
|
||||||
Spacer()
|
// Buttons
|
||||||
|
|
||||||
// Next/Open button
|
|
||||||
Button(action: {
|
Button(action: {
|
||||||
// Action for open button
|
// Action for first button
|
||||||
}) {
|
}) {
|
||||||
Text("Open")
|
Text("Upload from Gallery")
|
||||||
.frame(maxWidth: .infinity)
|
.frame(maxWidth: .infinity)
|
||||||
.padding()
|
.padding()
|
||||||
.foregroundColor(.black)
|
.foregroundColor(.black)
|
||||||
.background(
|
.background(
|
||||||
RoundedRectangle(cornerRadius: 25)
|
RoundedRectangle(cornerRadius: 25)
|
||||||
.fill(Color(red: 1.0, green: 0.714, blue: 0.271))
|
.fill(Color(red: 1.0, green: 0.973, blue: 0.871))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
Button(action: {
|
||||||
|
// Action for second button
|
||||||
|
}) {
|
||||||
|
Text("Take a Photo")
|
||||||
|
.frame(maxWidth: .infinity)
|
||||||
|
.padding()
|
||||||
|
.foregroundColor(.black)
|
||||||
|
.background(
|
||||||
|
RoundedRectangle(cornerRadius: 25)
|
||||||
|
.fill(Color(red: 1.0, green: 0.973, blue: 0.871))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
.padding(.bottom, 30)
|
|
||||||
.padding(.horizontal, 20)
|
|
||||||
}
|
}
|
||||||
.padding()
|
.padding()
|
||||||
.background(Color(.white))
|
.background(Color(.white))
|
||||||
|
|||||||
@ -43,8 +43,8 @@ struct WakeApp: App {
|
|||||||
} else {
|
} else {
|
||||||
// 根据登录状态显示不同视图
|
// 根据登录状态显示不同视图
|
||||||
if authState.isAuthenticated {
|
if authState.isAuthenticated {
|
||||||
// 已登录:显示主界面
|
// 已登录:显示userInfo页面
|
||||||
ContentView()
|
UserInfo()
|
||||||
.environmentObject(authState)
|
.environmentObject(authState)
|
||||||
} else {
|
} else {
|
||||||
// 未登录:显示登录界面
|
// 未登录:显示登录界面
|
||||||
@ -55,11 +55,11 @@ struct WakeApp: App {
|
|||||||
}
|
}
|
||||||
.onAppear {
|
.onAppear {
|
||||||
//3秒后自动隐藏启动页
|
//3秒后自动隐藏启动页
|
||||||
// DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
|
DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
|
||||||
// withAnimation {
|
withAnimation {
|
||||||
// showSplash = false
|
showSplash = false
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.modelContainer(container)
|
.modelContainer(container)
|
||||||
@ -91,10 +91,10 @@ struct WakeApp: App {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 3秒后自动隐藏启动页
|
// 3秒后自动隐藏启动页
|
||||||
// DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
|
DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
|
||||||
// withAnimation {
|
withAnimation {
|
||||||
// showSplash = false
|
showSplash = false
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user