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

52 lines
3.7 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
id: photo-capture
name: 照片采集与管理
area: rn-app
status: 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` prop**`transparent={true}` 在 Android 上使 Modal 继承父容器的渲染上下文(右侧面板),只遮盖面板区域而非全屏。改为非透明 Modal + 黑色背景,强制创建独立原生全屏窗口。