185 lines
7.6 KiB
Swift
185 lines
7.6 KiB
Swift
import SwiftUI
|
||
|
||
struct MediaUploadDemo: View {
|
||
@StateObject private var uploadManager = MediaUploadManager()
|
||
@State private var showMediaPicker = false
|
||
@State private var showUploadAlert = false
|
||
@State private var isUploading = false
|
||
|
||
var body: some View {
|
||
NavigationView {
|
||
VStack(spacing: 20) {
|
||
// 上传按钮
|
||
Button(action: {
|
||
showMediaPicker = true
|
||
}) {
|
||
Label("添加图片或视频", systemImage: "plus.circle.fill")
|
||
.font(.headline)
|
||
.frame(maxWidth: .infinity)
|
||
.padding()
|
||
.background(Color.blue)
|
||
.foregroundColor(.white)
|
||
.cornerRadius(10)
|
||
}
|
||
.padding(.horizontal)
|
||
.sheet(isPresented: $showMediaPicker) {
|
||
MediaPicker(
|
||
selectedMedia: $uploadManager.selectedMedia,
|
||
imageSelectionLimit: 2,
|
||
videoSelectionLimit: 2,
|
||
onDismiss: {
|
||
showMediaPicker = false
|
||
// 当媒体选择器关闭时,如果有选中的媒体,开始上传
|
||
if !uploadManager.selectedMedia.isEmpty {
|
||
isUploading = true
|
||
uploadManager.startUpload()
|
||
}
|
||
}
|
||
)
|
||
}
|
||
|
||
// 预览区域
|
||
if uploadManager.selectedMedia.isEmpty {
|
||
VStack(spacing: 16) {
|
||
Image(systemName: "photo.on.rectangle.angled")
|
||
.font(.system(size: 60))
|
||
.foregroundColor(.gray)
|
||
Text("暂无媒体文件")
|
||
.font(.headline)
|
||
.foregroundColor(.gray)
|
||
}
|
||
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
||
} else {
|
||
ScrollView {
|
||
LazyVGrid(columns: [GridItem(.adaptive(minimum: 120), spacing: 10)], spacing: 10) {
|
||
ForEach(0..<uploadManager.selectedMedia.count, id: \.self) { index in
|
||
MediaItemView(
|
||
media: uploadManager.selectedMedia[index],
|
||
status: uploadManager.uploadStatus["\(index)"] ?? .pending
|
||
)
|
||
.onTapGesture {
|
||
// 点击查看大图或播放视频
|
||
if case .video = uploadManager.selectedMedia[index] {
|
||
// 处理视频播放
|
||
print("Play video at index \(index)")
|
||
}
|
||
}
|
||
}
|
||
}
|
||
.padding()
|
||
}
|
||
}
|
||
|
||
// 显示上传状态
|
||
if isUploading {
|
||
VStack {
|
||
// 显示上传进度
|
||
if let progress = uploadManager.uploadStatus.values.compactMap({ status -> Double? in
|
||
if case .uploading(let progress) = status { return progress }
|
||
return nil
|
||
}).first {
|
||
ProgressView(value: progress, total: 1.0)
|
||
.padding(.horizontal)
|
||
Text("上传中 \(Int(progress * 100))%")
|
||
.font(.subheadline)
|
||
.foregroundColor(.gray)
|
||
} else {
|
||
ProgressView()
|
||
.progressViewStyle(CircularProgressViewStyle())
|
||
.scaleEffect(1.5)
|
||
Text("正在准备上传...")
|
||
.font(.subheadline)
|
||
.foregroundColor(.gray)
|
||
.padding(.top, 8)
|
||
}
|
||
}
|
||
.frame(maxWidth: .infinity)
|
||
.padding()
|
||
}
|
||
}
|
||
.alert(isPresented: $showUploadAlert) {
|
||
Alert(
|
||
title: Text(uploadManager.isAllUploaded ? "上传完成" : "上传状态"),
|
||
message: Text(uploadManager.isAllUploaded ?
|
||
"所有文件上传完成!" :
|
||
"正在处理上传..."),
|
||
dismissButton: .default(Text("确定"))
|
||
)
|
||
}
|
||
.onChange(of: uploadManager.uploadStatus) { _ in
|
||
// 检查是否所有上传都已完成或失败
|
||
let allFinished = uploadManager.uploadStatus.values.allSatisfy { status in
|
||
if case .completed = status { return true }
|
||
if case .failed = status { return true }
|
||
return false
|
||
}
|
||
|
||
if allFinished && !uploadManager.uploadStatus.isEmpty {
|
||
isUploading = false
|
||
showUploadAlert = true
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// 媒体项视图
|
||
struct MediaItemView: View {
|
||
let media: MediaType
|
||
let status: MediaUploadStatus
|
||
|
||
var body: some View {
|
||
ZStack(alignment: .bottom) {
|
||
// 缩略图
|
||
if let thumbnail = media.thumbnail {
|
||
Image(uiImage: thumbnail)
|
||
.resizable()
|
||
.scaledToFill()
|
||
.frame(width: 120, height: 120)
|
||
.cornerRadius(8)
|
||
.clipped()
|
||
|
||
// 视频标识
|
||
if media.isVideo {
|
||
Image(systemName: "play.circle.fill")
|
||
.font(.system(size: 30))
|
||
.foregroundColor(.white)
|
||
.shadow(radius: 5)
|
||
}
|
||
|
||
// 上传状态
|
||
VStack {
|
||
Spacer()
|
||
if case .uploading(let progress) = status {
|
||
ProgressView(value: progress, total: 1.0)
|
||
.progressViewStyle(LinearProgressViewStyle())
|
||
.frame(height: 4)
|
||
.padding(.horizontal, 4)
|
||
} else if case .completed = status {
|
||
Image(systemName: "checkmark.circle.fill")
|
||
.foregroundColor(.green)
|
||
.padding(4)
|
||
.background(Circle().fill(Color.white))
|
||
} else if case .failed = status {
|
||
Image(systemName: "exclamationmark.circle.fill")
|
||
.foregroundColor(.red)
|
||
.padding(4)
|
||
.background(Circle().fill(Color.white))
|
||
}
|
||
}
|
||
.padding(4)
|
||
}
|
||
}
|
||
.frame(width: 120, height: 120)
|
||
.overlay(
|
||
RoundedRectangle(cornerRadius: 8)
|
||
.stroke(Color.gray.opacity(0.3), lineWidth: 1)
|
||
)
|
||
}
|
||
}
|
||
|
||
// 预览
|
||
#Preview {
|
||
MediaUploadDemo()
|
||
.environmentObject(AuthState.shared)
|
||
} |