import SwiftUI import AVFoundation import Photos struct AppPermissionsView: View { @EnvironmentObject private var languageManager: LanguageManager @State private var cameraPermissionStatus: AVAuthorizationStatus = .notDetermined @State private var photoPermissionStatus: PHAuthorizationStatus = .notDetermined var body: some View { NavigationView { ZStack { // 背景渐变 LinearGradient( gradient: Gradient(colors: [ Color(.systemBackground), Color(.systemGray6).opacity(0.2) ]), startPoint: .top, endPoint: .bottom ) .ignoresSafeArea() ScrollView { VStack(spacing: 24) { // 顶部图标 VStack(spacing: 16) { ZStack { Circle() .fill( LinearGradient( gradient: Gradient(colors: [ Color.blue.opacity(0.1), Color.blue.opacity(0.05) ]), startPoint: .topLeading, endPoint: .bottomTrailing ) ) .frame(width: 80, height: 80) Image(systemName: "lock.shield") .font(.system(size: 36, weight: .light)) .foregroundColor(.blue) } Text("app_permissions".localized) .font(.system(size: 28, weight: .bold, design: .rounded)) .foregroundColor(.primary) .id(languageManager.refreshTrigger) } .padding(.top, 20) // 权限说明卡片 VStack(alignment: .leading, spacing: 16) { HStack { Image(systemName: "info.circle") .font(.system(size: 20, weight: .medium)) .foregroundColor(.blue) .frame(width: 32) Text("permissions_info".localized) .font(.system(size: 18, weight: .semibold)) Spacer() } Text("permissions_description".localized) .font(.system(size: 14)) .foregroundColor(.secondary) .lineLimit(nil) } .padding(20) .background( RoundedRectangle(cornerRadius: 16) .fill(Color(.systemBackground)) .shadow(color: .black.opacity(0.05), radius: 8, x: 0, y: 2) ) .padding(.horizontal, 20) // 相机权限卡片 PermissionCard( icon: "camera.fill", iconColor: .blue, title: "camera_permission".localized, description: "camera_permission_description".localized, status: cameraPermissionStatus.displayText, statusColor: cameraPermissionStatus.statusColor, action: { requestCameraPermission() }, actionTitle: cameraPermissionStatus.actionTitle ) // 相册权限卡片 PermissionCard( icon: "photo.fill", iconColor: .green, title: "photo_permission".localized, description: "photo_permission_description".localized, status: photoPermissionStatus.displayText, statusColor: photoPermissionStatus.statusColor, action: { requestPhotoPermission() }, actionTitle: photoPermissionStatus.actionTitle ) // 系统设置卡片 VStack(alignment: .leading, spacing: 16) { HStack { Image(systemName: "gearshape.fill") .font(.system(size: 20, weight: .medium)) .foregroundColor(.orange) .frame(width: 32) Text("system_settings".localized) .font(.system(size: 18, weight: .semibold)) Spacer() } Text("system_settings_description".localized) .font(.system(size: 14)) .foregroundColor(.secondary) .lineLimit(nil) Button(action: { openSystemSettings() }) { HStack { Image(systemName: "arrow.up.right.square") .font(.system(size: 16, weight: .medium)) Text("open_system_settings".localized) .font(.system(size: 16, weight: .medium)) } .foregroundColor(.white) .padding(.horizontal, 20) .padding(.vertical, 12) .background( RoundedRectangle(cornerRadius: 8) .fill(Color.blue) ) } } .padding(20) .background( RoundedRectangle(cornerRadius: 16) .fill(Color(.systemBackground)) .shadow(color: .black.opacity(0.05), radius: 8, x: 0, y: 2) ) .padding(.horizontal, 20) Spacer(minLength: 30) } } } .navigationTitle("App Permissions") .navigationBarTitleDisplayMode(.inline) .onAppear { checkPermissions() } } } // MARK: - 权限检查 private func checkPermissions() { cameraPermissionStatus = AVCaptureDevice.authorizationStatus(for: .video) photoPermissionStatus = PHPhotoLibrary.authorizationStatus() } // MARK: - 请求相机权限 private func requestCameraPermission() { AVCaptureDevice.requestAccess(for: .video) { granted in DispatchQueue.main.async { self.cameraPermissionStatus = granted ? .authorized : .denied } } } // MARK: - 请求相册权限 private func requestPhotoPermission() { PHPhotoLibrary.requestAuthorization { status in DispatchQueue.main.async { self.photoPermissionStatus = status } } } // MARK: - 打开系统设置 private func openSystemSettings() { if let settingsUrl = URL(string: UIApplication.openSettingsURLString) { UIApplication.shared.open(settingsUrl) } } } // MARK: - 权限卡片组件 struct PermissionCard: View { let icon: String let iconColor: Color let title: String let description: String let status: String let statusColor: Color let action: () -> Void let actionTitle: String var body: some View { VStack(alignment: .leading, spacing: 16) { HStack { Image(systemName: icon) .font(.system(size: 20, weight: .medium)) .foregroundColor(iconColor) .frame(width: 32) VStack(alignment: .leading, spacing: 4) { Text(title) .font(.system(size: 18, weight: .semibold)) Text(description) .font(.system(size: 14)) .foregroundColor(.secondary) } Spacer() } HStack { Text(status) .font(.system(size: 14, weight: .medium)) .foregroundColor(statusColor) Spacer() Button(action: action) { Text(actionTitle) .font(.system(size: 14, weight: .medium)) .foregroundColor(.white) .padding(.horizontal, 16) .padding(.vertical, 8) .background( RoundedRectangle(cornerRadius: 6) .fill(statusColor) ) } } } .padding(20) .background( RoundedRectangle(cornerRadius: 16) .fill(Color(.systemBackground)) .shadow(color: .black.opacity(0.05), radius: 8, x: 0, y: 2) ) .padding(.horizontal, 20) } } // MARK: - 权限状态扩展 extension AVAuthorizationStatus { var displayText: String { switch self { case .notDetermined: return "not_determined".localized case .restricted: return "restricted".localized case .denied: return "denied".localized case .authorized: return "authorized".localized @unknown default: return "unknown".localized } } var statusColor: Color { switch self { case .notDetermined: return .orange case .restricted, .denied: return .red case .authorized: return .green @unknown default: return .gray } } var actionTitle: String { switch self { case .notDetermined: return "request_permission".localized case .restricted, .denied: return "open_settings".localized case .authorized: return "permission_granted".localized @unknown default: return "unknown".localized } } } extension PHAuthorizationStatus { var displayText: String { switch self { case .notDetermined: return "not_determined".localized case .restricted: return "restricted".localized case .denied: return "denied".localized case .authorized: return "authorized".localized case .limited: return "limited".localized @unknown default: return "unknown".localized } } var statusColor: Color { switch self { case .notDetermined: return .orange case .restricted, .denied: return .red case .authorized, .limited: return .green @unknown default: return .gray } } var actionTitle: String { switch self { case .notDetermined: return "request_permission".localized case .restricted, .denied: return "open_settings".localized case .authorized, .limited: return "permission_granted".localized @unknown default: return "unknown".localized } } } #Preview { AppPermissionsView() .environmentObject(LanguageManager.shared) }