import 'dart:io'; import 'package:image_picker/image_picker.dart'; import 'package:sino_med_cloud/core/utils/logger.dart'; import 'package:sino_med_cloud/core/utils/toast_utils.dart'; import 'package:sino_med_cloud/permission/permission_service.dart'; import 'media_exception.dart'; /// 相册和快速拍照服务 /// /// 适合普通拍照、表单上传、医疗资料拍照(非实时) /// /// 使用示例: /// ```dart /// // 从相册选择 /// final file = await PickerService.pickFromGallery(); /// /// // 使用系统相机拍照 /// final photo = await PickerService.pickFromCamera(); /// ``` class PickerService { static final ImagePicker _picker = ImagePicker(); /// 默认图片质量(1-100) static const int defaultImageQuality = 90; /// 从相册选择图片 /// /// - [imageQuality] 图片质量(1-100),默认 90 /// - [maxWidth] 最大宽度,null 表示不限制 /// - [maxHeight] 最大高度,null 表示不限制 /// /// 返回选择的图片文件,如果用户取消选择返回 null /// /// 抛出 [MediaException] 如果选择失败 static Future pickFromGallery({ int imageQuality = defaultImageQuality, double? maxWidth, double? maxHeight, }) async { try { // 检查相册权限 final permissionResult = await PermissionService.request(PermissionType.gallery); if (permissionResult != PermissionResult.granted) { if (permissionResult == PermissionResult.permanentlyDenied) { ToastUtils.showError('相册权限被永久拒绝,请在设置中开启相册权限'); // 自动打开设置页面 await PermissionService.openSetting(); throw MediaPermissionException('相册权限被永久拒绝,已引导用户前往设置'); } else { ToastUtils.showError('需要相册权限才能选择图片'); throw MediaPermissionException('相册权限被拒绝'); } } AppLogger.d('开始从相册选择图片...'); final XFile? file = await _picker.pickImage( source: ImageSource.gallery, imageQuality: imageQuality, maxWidth: maxWidth, maxHeight: maxHeight, ); if (file == null) { AppLogger.d('用户取消了相册选择'); return null; } final imageFile = File(file.path); if (!await imageFile.exists()) { throw MediaFileException('选择的图片文件不存在: ${file.path}'); } AppLogger.d('相册选择成功: ${file.path}'); return imageFile; } on MediaException { rethrow; } catch (e) { AppLogger.e('相册选择失败', e); if (e.toString().contains('permission') || e.toString().contains('权限')) { throw MediaPermissionException( '相册访问权限被拒绝,请在设置中开启相册权限', originalError: e, ); } throw MediaException( '相册选择失败: ${e.toString()}', originalError: e, ); } } /// 使用系统相机拍照(轻量级) /// /// - [imageQuality] 图片质量(1-100),默认 90 /// - [maxWidth] 最大宽度,null 表示不限制 /// - [maxHeight] 最大高度,null 表示不限制 /// /// 返回拍摄的照片文件,如果用户取消拍照返回 null /// /// 抛出 [MediaException] 如果拍照失败 static Future pickFromCamera({ int imageQuality = defaultImageQuality, double? maxWidth, double? maxHeight, }) async { try { // 检查相机权限 final permissionResult = await PermissionService.request(PermissionType.camera); if (permissionResult != PermissionResult.granted) { if (permissionResult == PermissionResult.permanentlyDenied) { ToastUtils.showError('相机权限被永久拒绝,请在设置中开启相机权限'); // 自动打开设置页面 await PermissionService.openSetting(); throw MediaPermissionException('相机权限被永久拒绝,已引导用户前往设置'); } else { ToastUtils.showError('需要相机权限才能拍照'); throw MediaPermissionException('相机权限被拒绝'); } } AppLogger.d('开始使用系统相机拍照...'); final XFile? file = await _picker.pickImage( source: ImageSource.camera, imageQuality: imageQuality, maxWidth: maxWidth, maxHeight: maxHeight, ); if (file == null) { AppLogger.d('用户取消了拍照'); return null; } final photoFile = File(file.path); if (!await photoFile.exists()) { throw MediaFileException('拍摄的照片文件不存在: ${file.path}'); } AppLogger.d('拍照成功: ${file.path}'); return photoFile; } on MediaException { rethrow; } catch (e) { AppLogger.e('相机拍照失败', e); if (e.toString().contains('permission') || e.toString().contains('权限')) { throw MediaPermissionException( '相机权限被拒绝,请在设置中开启相机权限', originalError: e, ); } throw MediaException( '相机拍照失败: ${e.toString()}', originalError: e, ); } } /// 从相册选择视频 /// /// 返回选择的视频文件,如果用户取消选择返回 null /// /// 抛出 [MediaException] 如果选择失败 static Future pickVideoFromGallery() async { try { // 检查相册权限 final permissionResult = await PermissionService.request(PermissionType.gallery); if (permissionResult != PermissionResult.granted) { if (permissionResult == PermissionResult.permanentlyDenied) { ToastUtils.showError('相册权限被永久拒绝,请在设置中开启相册权限'); // 自动打开设置页面 await PermissionService.openSetting(); throw MediaPermissionException('相册权限被永久拒绝,已引导用户前往设置'); } else { ToastUtils.showError('需要相册权限才能选择视频'); throw MediaPermissionException('相册权限被拒绝'); } } AppLogger.d('开始从相册选择视频...'); final XFile? file = await _picker.pickVideo( source: ImageSource.gallery, ); if (file == null) { AppLogger.d('用户取消了视频选择'); return null; } final videoFile = File(file.path); if (!await videoFile.exists()) { throw MediaFileException('选择的视频文件不存在: ${file.path}'); } AppLogger.d('视频选择成功: ${file.path}'); return videoFile; } on MediaException { rethrow; } catch (e) { AppLogger.e('视频选择失败', e); if (e.toString().contains('permission') || e.toString().contains('权限')) { throw MediaPermissionException( '相册访问权限被拒绝,请在设置中开启相册权限', originalError: e, ); } throw MediaException( '视频选择失败: ${e.toString()}', originalError: e, ); } } }