import SwiftUI import PhotosUI /// VisionKit 在模拟器不可用,demo / 验证场景走 PhotosPicker 回退选已有照片。 /// 真机正式录入走 DocumentScannerView。 struct PhotoPickerSheet: View { let onFinish: ([UIImage]) -> Void let onCancel: () -> Void @State private var selection: [PhotosPickerItem] = [] @State private var loading = false var body: some View { VStack(spacing: 20) { Image(systemName: "photo.on.rectangle.angled") .font(.system(size: 56)) .foregroundStyle(Tj.Palette.text3) Text("模拟器没有摄像头,从相册选一张化验单/体检报告") .font(.system(size: 13)) .foregroundStyle(Tj.Palette.text2) .multilineTextAlignment(.center) PhotosPicker(selection: $selection, maxSelectionCount: 5, matching: .images) { Text("从相册选 ≤5 张") .font(.system(size: 14, weight: .semibold)) .frame(maxWidth: .infinity) .padding(.vertical, 12) .background(Tj.Palette.ink) .foregroundStyle(Tj.Palette.paper) .clipShape(Capsule()) } Button("取消", action: onCancel) .foregroundStyle(Tj.Palette.text3) if loading { ProgressView().tint(Tj.Palette.ink) } } .padding(28) .frame(maxWidth: .infinity, maxHeight: .infinity) .background(Tj.Palette.sand.ignoresSafeArea()) .onChange(of: selection) { _, newValue in guard !newValue.isEmpty else { return } loadImages(from: newValue) } } private func loadImages(from items: [PhotosPickerItem]) { loading = true Task { var images: [UIImage] = [] for item in items { if let data = try? await item.loadTransferable(type: Data.self), let img = UIImage(data: data) { images.append(img) } } await MainActor.run { loading = false if images.isEmpty { onCancel() } else { onFinish(images) } } } } }