react-phone-apps/.blueprint/modules/ai-recognize.md
lanrtop e7ab0d1ef1 feat: 汇总页新增聚合/分组视图与纯数据导出,实现地图侧栏聚合视图
- summary 新增明细/聚合/分组三 Tab,对应 SummaryAggregateList(楼层→分类)
  和 SummaryGroupList(按物品名分组,可展开查看分布位置)
- 新增 exportDataOnly() 仅导出 CSV 不含照片,header 新增两个导出按钮
- MarkerList 聚合 Tab 从 placeholder 升级为按颜色+分类分组的实际视图
- 蓝图新增 ai-recognize 模块(planned),引入 expo-image-manipulator /
  expo-secure-store 依赖为后续 AI 识别功能做准备

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-10 18:02:22 +09:00

69 lines
4.7 KiB
Markdown
Raw 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: ai-recognize
name: AI 照片识别填充表单
area: rn-app
status: planned
---
## 概述
用户在物品登记表单中,选取当前物品的一张或多张照片,可附加文字补充描述,发送给通义千问 Qwen-VL-Max 进行多模态识别。AI 返回富文本描述后,用户在回复文本中框选任意片段,点击字段注入按钮将其填入表单对应字段(名称、规格、单价、单位、备注)。
## 技术选型
- **API**:通义千问 Qwen-VL-Max阿里云灵积 DashScopeOpenAI 兼容格式)
- **多图策略**:多轮对话叠加(每轮可追加图片或文字)
- **选区注入**TextInput selectable + lastSelectionRefblur 安全)
- **图片压缩**expo-image-manipulator600px / 0.65 质量,约 60KB/张)
- **密钥存储**expo-secure-store
## 新增依赖
```
expo-secure-store # API Key / access_token 加密存储
expo-image-manipulator # 识别前压缩图片
```
## 任务卡
### 📋 通义千问 API 服务层
- status: todo
- complexity: S
- files: apps/property-survey/src/services/qianfanAI.ts
- acceptance: 封装 DashScope OpenAI 兼容接口getApiKey() / saveApiKey() 读写 SecureStorechat(messages) 发送多轮对话(支持 image_url + text content 混合token 不存在时抛出带中文提示的 Error网络/鉴权失败统一抛出可读错误;导出 QianfanMessage 类型
### 📋 API Key 设置 UI
- status: todo
- complexity: S
- files: apps/property-survey/src/features/settings/QianfanApiSettings.tsx
- depends: ai-recognize
- acceptance: 含 API Key 输入框secureTextEntry和保存按钮「测试连接」按钮调 qianfanAI.chat 发一条纯文字 ping成功显示绿色"连通 ✓",失败显示红色错误原因;组件可独立渲染,供后续接入设置入口
### 📋 useAiRecognize hook
- status: todo
- complexity: M
- files: apps/property-survey/src/features/recognize/useAiRecognize.ts
- depends: ai-recognize
- acceptance: 接收 photos: Photo[] 参数;管理 selectedIdstogglePhoto 切换、hint 文字、messages 历史、loading、response、error 状态lastSelectionRef 仅在 end>start 时更新blur 不清空getSelectedText() 从 lastSelectionRef 提取 response 子串recognize() 将选中照片 filePath 用 expo-image-manipulator 压缩后转 base64拼入 messages调 qianfanAI.chat追加 AI 回复到 messages 并更新 response未配置 API Key 时 throw 并在 error 中显示引导文字;支持多轮追加(再次调 recognize() 时保留 messages 历史)
### 📋 AI 识别面板 UI
- status: todo
- complexity: M
- files: apps/property-survey/src/features/recognize/AiRecognizePanel.tsx, apps/property-survey/src/features/recognize/PhotoSelector.tsx, apps/property-survey/src/features/recognize/InjectionToolbar.tsx
- depends: ai-recognize
- acceptance: AiRecognizePanel 为全屏 Modal顶部 PhotoSelector 横向滚动展示照片缩略图选中项右上角绿色勾hint TextInput 单行placeholder"补充描述,如品牌型号…");「识别」按钮 loading 时显示 ActivityIndicatorresponse 区域用 multiline TextInputeditable=falseselectable=trueonSelectionChange 更新 hook底部 InjectionToolbar 固定显示「→名称」「→规格」「→单价」「→单位」「→备注」5个按钮点击时调 onInject(field, selectedText)selectedText 为空时按钮 disabled注入成功后对应按钮短暂变绿300mserror 非空时在 response 区上方显示红色提示条
### 📋 表单接线
- status: todo
- complexity: S
- files: apps/property-survey/src/features/item/useItemForm.ts, apps/property-survey/src/features/item/ItemFields.tsx
- depends: ai-recognize
- acceptance: useItemForm 新增 injectField(key: keyof FormState, value: string) 方法(调 setField 并标记 isDirtyItemFields 照片列顶部「照片」标题行右侧增加「✨ AI」文字按钮仅 photoItemId 非空时显示);点击打开 AiRecognizePanel Modal传入当前物品照片列表和 injectField 回调;注入后 Modal 保持打开,用户可继续框选其他字段
## 决策记录
- 选用通义千问 Qwen-VL-Max阿里电商生态训练数据对家具/家电/品牌商品识别最准,且价格为同档位最低(约 0.003元/千token
- 多轮对话而非一次性多图:允许用户逐步追加照片和追问,比一次提交更灵活
- TextInput selectable 方案而非分句 Chip原生文本选择体验与系统一致且支持任意粒度框选如只选价格数字用 lastSelectionRef 解决 blur 丢选区问题
- 图片压缩到 600px/0.65:实测约 55-70KB/张3张约 200KB在 4MB API 限制内且不明显影响识别准确度