react-phone-apps/.blueprint/modules/photo-capture.md
lanrtop 1c6d491eaf feat: 全屏照片预览支持捏合缩放与拖动查看
- MarkerPhotoPanel:基于 RNGH PinchGesture + Reanimated 实现捏合缩放(1x~5x);放大后可双指拖动,放大模式下禁用左右切图手势
- _layout:根布局包裹 GestureHandlerRootView,解决 Modal 内手势失效问题
- 蓝图:新增 pdf-report 模块(concept),photo-capture 补充缩放任务卡(done)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-10 08:50:54 +09:00

3.7 KiB
Raw Blame History

id name area status
photo-capture 照片采集与管理 rn-app done

概述

调用设备摄像头或相册为物品条目添加多张照片,照片存储到 App 专属目录,路径写入 SQLite photos 表。支持 Android 13+ 权限模型CAMERA + READ_MEDIA_IMAGES + FileProvider

任务卡

摄像头调用与照片存储

  • status: done
  • complexity: M
  • files: apps/property-survey/src/features/photo/usePhotoCapture.ts, apps/property-survey/src/features/photo/PhotoPicker.tsx
  • depends: local-data-layer
  • acceptance: 使用 expo-image-pickerMediaType.Images已从废弃的 MediaTypeOptions 迁移「拍照」和「从相册选择」两种入口Alert 关闭后延迟 300ms 启动,避免与系统权限弹窗冲突;照片复制到 App 专属目录expo-file-system调用 insertPhoto 写入数据库;有权限检查

Android 权限与 FileProvider 配置

  • status: done
  • complexity: S
  • files: apps/property-survey/android/app/src/main/AndroidManifest.xml, apps/property-survey/android/app/src/main/res/xml/file_paths.xml, apps/property-survey/app.json
  • acceptance: AndroidManifest 声明 CAMERA + READ_MEDIA_IMAGES 权限(兼容 Android 13+);配置 FileProviderandroid:authorities="${applicationId}.provider")支持相机临时文件 URIapp.json 中 expo-image-picker 插件配置中文权限说明

照片网格预览与删除(物品表单内)

  • status: done
  • complexity: M
  • files: apps/property-survey/src/features/photo/PhotoGrid.tsx
  • depends: photo-capture
  • acceptance: 3 列网格展示已添加的照片缩略图点击照片全屏预览FlatList + pagingEnabled + getItemLayout使用 useWindowDimensions 实时宽度计算每页偏移全屏预览顶部有「保存到相册」按钮expo-media-library保存后显示"已保存"提示);长按照片显示「删除」确认弹窗,删除时同步调用 deletePhoto含文件系统删除末尾显示「+」按钮触发 PhotoPicker

查看模式照片面板MarkerPhotoPanel

  • status: done
  • complexity: M
  • files: apps/property-survey/src/features/photo/MarkerPhotoPanel.tsx
  • depends: photo-capture
  • acceptance: 查看模式下右侧面板按物品分组展示照片缩略图4 列网格 + 物品名标题);点击缩略图全屏 Modal 预览Modal 为非透明全屏黑底(解决 Android transparent Modal 仅覆盖父容器的问题);单张显示 + onTouchStart/End 手势滑动切换≥50px 触发)+ 左右箭头按钮;计数器实时同步

全屏预览捏合缩放

  • status: done
  • complexity: M
  • files: apps/property-survey/src/features/photo/MarkerPhotoPanel.tsx
  • depends: photo-capture
  • acceptance: 全屏预览 Modal 内支持双指捏合缩放(基于 react-native-gesture-handler PinchGestureHandler + react-native-reanimated缩放后可双指拖动查看细节缩放比例 1x 时滑动手势正常切换照片,缩放比例 > 1x 时禁用切换手势;双击照片在 1x 和 2x 之间切换

决策记录

  • 照片预览放弃 ScrollView/FlatList pagingEnabled:在 Android 上 transparent Modal 的渲染范围被限制在父组件(右侧 260px 面板)内而非全屏,导致 pagingEnabled 页宽与实际视口不匹配,两张照片始终并排显示。尝试多种宽度测量方案(SCREEN_W 静态值、onLayout 动态测量、useWindowDimensions)均无效。最终改为单张显示 + 原生 Touch 事件手势,彻底绕开分页宽度问题。
  • Modal 去掉 transparent proptransparent={true} 在 Android 上使 Modal 继承父容器的渲染上下文(右侧面板),只遮盖面板区域而非全屏。改为非透明 Modal + 黑色背景,强制创建独立原生全屏窗口。