Day 3:拍照识题 + 存储架构升级(2026-06-07)

8 阅读3分钟

Day 3:拍照识题 + 存储架构升级(2026-06-07)

1. 拍照识题 + OCR 流式输出

完整链路:相机/相册选图 → 图片预览 → 发送到 /api/ocr → MIMO v2.5 多模态识别 → SSE 流式返回 → 逐 token 渲染结构化结果。

// API 路由:转发 MIMO SSE 流
const response = await fetch(MIMO_API_URL, {
  body: JSON.stringify({ model: "mimo-v2.5", stream: true, messages: [
    { role: "system", content: "结构化输出:题干、知识点、分析思路、参考答案" },
    { role: "user", content: [
      { type: "text", text: "请识别这道题目" },
      { type: "image_url", image_url: { url: `data:${mime};base64,${base64}` } }
    ]}
  ]}),
});
// 转发 SSE 到客户端

前端流式消费:用 ReadableStream + getReader() 逐 token 更新 OCR 结果消息。

UI 细节

  • 图片独立显示(不包裹在气泡内),点击全屏预览
  • 有文字时文字在图片下方单独气泡内
  • 「📝 保存到错题本」占位按钮

2. 存储架构升级:localStorage → Dexie + TanStack Query

为什么升级:localStorage 只有 5MB 限制,同步读写阻塞主线程。Dexie (IndexedDB) 无容量限制,异步读写,支持结构化查询。

新架构

localStorage (zustand)  →  配置、token、UI 状态(小数据、同步)
Dexie (IndexedDB)       →  聊天消息、OCR 记录(大数据、异步)
TanStack Query          →  内存缓存层(Dexie ↔ UI 的桥梁)

关键设计决策

  • 直接用 Dexie 跳过 localForage,省去 Phase 2 迁移
  • TanStack Query 作为内存缓存,Phase 2 可无缝对接后端 API
  • ChatPage 拆分为父组件(Dexie 加载)+ 子组件(useChat),解决 initialMessages 时序问题

3. 持久化踩坑实录

这次存储迁移经历了 13 次提交的迭代修复,是项目至今最密集的 debug 过程:

问题根因修复
消息无限循环messages 每 token 新引用作 effect 依赖改用 messages.length + messagesRef
TDZ 错误ref 初始化在 useChat 之前移到 useChat 之后
渲染警告render 期间赋值 ref移入 useLayoutEffect
AI 回复丢失persistence effect 缺 isLoading 依赖添加依赖
useChat 不读新数据initialMessages 只首次生效父子组件拆分
Dexie 无限写入mutation 对象放 effect 依赖改用 ref 持有
消息顺序错乱toArray() 按主键排序加 order 字段
OCR 数据丢失Dexie v2 schema 遗漏 ocrRecords 表补回表定义

最后一个 bug(Dexie v2 schema)是最隐蔽的:Dexie 升级时会删除未列出的表,导致 OCR 表每次打开数据库都被销毁。

4. /simplify 审查发现

发现严重度状态
Dexie v2 遗漏 ocrRecords 表🔴 Critical✅ 已修复
beforeunload 无事务保护🟡 High✅ 已修复
visibilitychange listener 泄漏🟡 High✅ 已修复
SSE 尾部 buffer 未刷新🟡 Medium✅ 已修复
setTimeout(100) 保存不可靠🟡 Medium⚠️ 待优化
SSE 解析代码重复🔵 Low跳过

当前技术栈 & 方案选型

领域技术选型选型理由
前端框架Next.js 16 (App Router)RSC + 流式 SSR + API Routes
UI 组件shadcn/ui + Tailwind 4高质量组件 + 原子化 CSS
状态管理zustand + persist轻量 + TypeScript 友好
服务端缓存TanStack Query内存缓存 + 后续对接 API
本地持久化Dexie (IndexedDB)无容量限制 + 结构化查询
AI 流式输出Vercel AI SDK (streamText + useChat)一站式 SSE 解决方案
AI 模型DeepSeek + MIMO v2.5文字用 DeepSeek,视觉用 MIMO
Markdown 渲染react-markdown + remark-gfm流式友好 + 完整 GFM 支持
包管理npm workspaces (Monorepo)pnpm 在 Windows 有权限问题
移动端PWA + 移动优先布局接近原生 App 体验

Phase 2 规划(后端工程化)

  1. NestJS 后端:替换 Next.js API Route,Controller → Service → Repository
  2. Prisma + PostgreSQL:用户、消息、错题数据入库(唯一真值来源)
  3. Redis:接口缓存、登录态、限流
  4. JWT 认证:access token / refresh token 双 token
  5. TanStack Query 对接 API:前端 Dexie 降级为离线缓存
  6. 对象存储(OSS/MinIO):图片、大文件;PG 只存 URL
  7. 上下文长度限制:滑动窗口截断,避免 token 超限

项目持续更新中,每天记录开发进度和技术决策。