import SwiftUI import os.log /// 多图上传示例视图 /// 展示如何使用 MultiImageUploader 组件实现多图上传功能 @available(iOS 16.0, *) struct MultiImageUploadExampleView: View { // MARK: - 状态属性 @State private var uploadResults: [UploadResult] = [] @State private var isShowingUploader = false @State private var showUploadAlert = false @State private var alertMessage = "" @State private var isUploading = false private let logger = Logger(subsystem: "com.yourapp.uploader", category: "MultiImageUploadExample") // MARK: - 视图主体 var body: some View { NavigationView { VStack(spacing: 16) { // 上传按钮和状态 uploadButton // 上传统计信息 if !uploadResults.isEmpty { uploadStatsView } // 上传进度列表 uploadProgressList Spacer() } .navigationTitle("多图上传示例") .toolbar { // 清空按钮 if !uploadResults.isEmpty && !isUploading { Button("清空") { withAnimation { uploadResults.removeAll() } } } } .sheet(isPresented: $isShowingUploader) { // 多图上传组件 MultiImageUploader( maxSelection: 10 ) { results in processUploadResults(results) } } .alert("上传结果", isPresented: $showUploadAlert) { Button("确定", role: .cancel) { } } message: { Text(alertMessage) } } } // MARK: - 子视图 /// 上传按钮 private var uploadButton: some View { Button(action: { isShowingUploader = true }) { Label("选择并上传图片", systemImage: "photo.on.rectangle.angled") .font(.headline) .foregroundColor(.white) .padding() .frame(maxWidth: .infinity) .background(Color.blue) .cornerRadius(10) } .padding(.horizontal) .padding(.top) } /// 上传统计信息 private var uploadStatsView: some View { VStack(alignment: .leading, spacing: 8) { let successCount = uploadResults.filter { $0.status == .success }.count let inProgressCount = uploadResults.filter { if case .uploading = $0.status { return true } return false }.count let failedCount = uploadResults.count - successCount - inProgressCount Text("上传统计") .font(.headline) HStack { StatView( value: "\(uploadResults.count)", label: "总数量", color: .blue ) StatView( value: "\(successCount)", label: "成功", color: .green ) StatView( value: "\(inProgressCount)", label: "上传中", color: .orange ) StatView( value: "\(failedCount)", label: "失败", color: .red ) } // 总进度条 if inProgressCount > 0 { let progress = uploadResults.reduce(0.0) { result, uploadResult in if case .uploading(let progress) = uploadResult.status { return result + progress } else if uploadResult.status == .success { return result + 1.0 } return result } / Double(uploadResults.count) VStack(alignment: .leading, spacing: 4) { Text("总进度: \(Int(progress * 100))%") .font(.subheadline) ProgressView(value: progress) .progressViewStyle(LinearProgressViewStyle(tint: .blue)) } .padding(.top, 8) } } .padding() .background(Color(.systemGray6)) .cornerRadius(10) .padding(.horizontal) } /// 上传进度列表 private var uploadProgressList: some View { List { ForEach($uploadResults) { $result in VStack(alignment: .leading, spacing: 8) { // 图片缩略图和状态 HStack { // 图片缩略图 Image(uiImage: result.image) .resizable() .scaledToFill() .frame(width: 60, height: 60) .clipped() .cornerRadius(8) .overlay( RoundedRectangle(cornerRadius: 8) .stroke(borderColor(for: result.status), lineWidth: 1) ) // 状态和进度 VStack(alignment: .leading, spacing: 4) { Text("图片 \(result.id.uuidString.prefix(8))...") .font(.subheadline) switch result.status { case .uploading(let progress): VStack(alignment: .leading, spacing: 4) { Text("上传中: \(Int(progress * 100))%") .font(.caption) ProgressView(value: progress) .progressViewStyle(LinearProgressViewStyle()) } case .success: HStack { Image(systemName: "checkmark.circle.fill") .foregroundColor(.green) Text("上传成功") .font(.caption) .foregroundColor(.green) } case .failure(let error): HStack { Image(systemName: "exclamationmark.triangle.fill") .foregroundColor(.red) Text("上传失败: \(error.localizedDescription)") .font(.caption) .foregroundColor(.red) } case .idle: Text("等待上传...") .font(.caption) .foregroundColor(.secondary) } } Spacer() } .padding(.vertical, 4) } .padding(.vertical, 8) .listRowSeparator(.hidden) } } .listStyle(PlainListStyle()) .animation(.easeInOut, value: uploadResults) } // MARK: - 辅助方法 /// 获取状态对应的边框颜色 private func borderColor(for status: UploadStatus) -> Color { switch status { case .success: return .green case .failure: return .red case .uploading: return .blue case .idle: return .gray } } /// 处理上传结果 private func processUploadResults(_ results: [UploadResult]) { // 更新状态 isUploading = results.contains { result in if case .uploading = result.status { return true } return false } // 更新结果 withAnimation { uploadResults = results isShowingUploader = false } // 检查是否全部完成 let allFinished = !results.contains { result in if case .uploading = result.status { return true } if case .idle = result.status { return true } return false } if allFinished { let successCount = results.filter { $0.status == .success }.count let totalCount = results.count alertMessage = "上传完成\n成功: \(successCount)/\(totalCount)" showUploadAlert = true isUploading = false logger.info("上传完成,成功: \(successCount)/\(totalCount)") } } } // MARK: - 子视图 /// 统计信息视图 private struct StatView: View { let value: String let label: String let color: Color var body: some View { VStack { Text(value) .font(.title3.bold()) .foregroundColor(color) Text(label) .font(.caption) .foregroundColor(.secondary) } .frame(maxWidth: .infinity) } } // MARK: - 预览 @available(iOS 16.0, *) struct MultiImageUploadExampleView_Previews: PreviewProvider { static var previews: some View { MultiImageUploadExampleView() } }