当您提供代码差异后,我将按照以下格式生成: ``` <type>(<scope>): <subject> <body> ``` 其中type会根据更改类型选择(feat、fix、docs、style、refactor等),scope表示影响范围,subject简要描述变更内容,body详细说明修改内容。
69 lines
2.3 KiB
Swift
69 lines
2.3 KiB
Swift
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(.tjScaled( 56))
|
|
.foregroundStyle(Tj.Palette.text3)
|
|
Text("模拟器没有摄像头,从相册选一张化验单/体检报告")
|
|
.font(.tjScaled( 13))
|
|
.foregroundStyle(Tj.Palette.text2)
|
|
.multilineTextAlignment(.center)
|
|
|
|
PhotosPicker(selection: $selection,
|
|
maxSelectionCount: 5,
|
|
matching: .images) {
|
|
Text("从相册选 ≤5 张")
|
|
.font(.tjScaled( 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) }
|
|
}
|
|
}
|
|
}
|
|
}
|