189 lines
7.8 KiB
Swift
189 lines
7.8 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 {
|
|
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: Binding(
|
|
get: { uploadManager.selectedMedia },
|
|
set: { newMedia in
|
|
uploadManager.clearAllMedia()
|
|
uploadManager.addMedia(newMedia)
|
|
}
|
|
),
|
|
imageSelectionLimit: 1,
|
|
videoSelectionLimit: 0,
|
|
allowedMediaTypes: .imagesOnly,
|
|
selectionMode: .single,
|
|
onDismiss: {
|
|
showMediaPicker = false
|
|
if !uploadManager.selectedMedia.isEmpty {
|
|
// Start upload logic here
|
|
}
|
|
}
|
|
)
|
|
}
|
|
|
|
// 预览区域
|
|
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)
|
|
} |