import SwiftUI import PhotosUI /// 帮助与反馈:内容 + 联系方式 + 可选截图(≤3 张,压缩后上传)。 struct FeedbackView: View { @Environment(\.dismiss) private var dismiss @State private var content = "" @State private var contact = "" @State private var pickedItems: [PhotosPickerItem] = [] @State private var imageDatas: [Data] = [] @State private var submitting = false @State private var toast: String? private let service = FeedbackService() var body: some View { Form { Section("反馈内容") { TextField("说说你遇到的问题或建议…", text: $content, axis: .vertical) .lineLimit(4...8) } Section("联系方式(选填)") { TextField("手机号 / 微信,方便我们联系你", text: $contact) } Section("截图(选填)") { PhotosPicker(selection: $pickedItems, maxSelectionCount: 3, matching: .images) { Label("添加截图", systemImage: "photo.on.rectangle") } if !imageDatas.isEmpty { Text("已选 \(imageDatas.count) 张").font(.caption).foregroundStyle(.secondary) } } Section { Button { Task { await submit() } } label: { Text(submitting ? "提交中…" : "提交反馈").frame(maxWidth: .infinity) } .disabled(submitting || content.isEmpty) } } .navigationTitle("帮助与反馈") .navigationBarTitleDisplayMode(.inline) .onChange(of: pickedItems) { _, items in Task { await loadImages(items) } } .overlay(alignment: .bottom) { toastView } } @ViewBuilder private var toastView: some View { if let toast { Text(toast) .font(.subheadline) .padding(.horizontal, 16).padding(.vertical, 10) .background(.black.opacity(0.8)).foregroundStyle(.white) .clipShape(Capsule()).padding(.bottom, 30) .task(id: toast) { try? await Task.sleep(for: .milliseconds(1500)) if toast.contains("成功") { dismiss() } else { self.toast = nil } } } } private func loadImages(_ items: [PhotosPickerItem]) async { var datas: [Data] = [] for item in items { if let raw = try? await item.loadTransferable(type: Data.self), let jpeg = ImageDownsampler.jpeg(raw) { datas.append(jpeg) } } imageDatas = datas } private func submit() async { submitting = true defer { submitting = false } do { _ = try await service.submit(content: content, contact: contact, images: imageDatas) toast = "提交成功,感谢反馈" } catch { toast = (error as? LocalizedError)?.errorDescription ?? "提交失败,请重试" } } }