2026-02-24 18:18:27 +08:00
|
|
|
|
# CLAUDE.md
|
|
|
|
|
|
|
|
|
|
|
|
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
|
|
|
|
|
|
|
|
|
|
## 项目概述
|
|
|
|
|
|
|
|
|
|
|
|
**PicAnalysis** 是一个图片 OCR 与智能文档管理系统,支持从截图中提取文字、AI 智能分析标签分类,并将识别结果转化为待办事项或归档文档。
|
|
|
|
|
|
|
|
|
|
|
|
### 技术栈
|
|
|
|
|
|
- **前端**: React 19 + TypeScript + Vite + Tailwind CSS + Zustand + TanStack Query + React Router v7
|
|
|
|
|
|
- **后端**: Node.js + Express + TypeScript + Prisma ORM
|
|
|
|
|
|
- **数据库**: SQLite (开发) / PostgreSQL (生产)
|
|
|
|
|
|
- **认证**: JWT + bcrypt
|
|
|
|
|
|
- **测试**: Vitest (前端单元测试), Playwright (E2E 测试), Jest (后端测试)
|
|
|
|
|
|
|
|
|
|
|
|
## 开发命令
|
|
|
|
|
|
|
|
|
|
|
|
### 后端 (端口 4000)
|
|
|
|
|
|
```bash
|
|
|
|
|
|
cd backend
|
|
|
|
|
|
npm run dev # 启动开发服务器 (tsx watch)
|
|
|
|
|
|
npm run build # TypeScript 编译
|
|
|
|
|
|
npm run start # 运行生产构建
|
|
|
|
|
|
npm run test # 运行 Jest 测试
|
|
|
|
|
|
npm run test:watch # Jest 监视模式
|
|
|
|
|
|
npm run test:coverage # 测试覆盖率报告
|
|
|
|
|
|
npm run lint # ESLint 检查
|
|
|
|
|
|
npm run lint:fix # ESLint 自动修复
|
2026-02-26 14:00:22 +08:00
|
|
|
|
npm run format # Prettier 格式化
|
2026-02-24 18:18:27 +08:00
|
|
|
|
npm run prisma:generate # 生成 Prisma Client
|
|
|
|
|
|
npm run prisma:migrate # 运行数据库迁移
|
|
|
|
|
|
npm run prisma:studio # 打开 Prisma Studio
|
2026-02-26 14:00:22 +08:00
|
|
|
|
|
|
|
|
|
|
# 运行单个测试文件
|
|
|
|
|
|
npm test -- tests/unit/services/auth.service.test.ts
|
|
|
|
|
|
npm test -- --testNamePattern="should login"
|
2026-02-24 18:18:27 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 前端 (端口 3000)
|
|
|
|
|
|
```bash
|
|
|
|
|
|
cd frontend
|
|
|
|
|
|
npm run dev # 启动 Vite 开发服务器
|
|
|
|
|
|
npm run build # 构建生产版本
|
|
|
|
|
|
npm run preview # 预览生产构建
|
|
|
|
|
|
npm run test # 运行 Vitest 单元测试
|
|
|
|
|
|
npm run test:ui # Vitest UI 界面
|
|
|
|
|
|
npm run test:coverage # Vitest 覆盖率报告
|
|
|
|
|
|
npm run test:e2e # 运行 Playwright E2E 测试
|
|
|
|
|
|
npm run test:e2e:ui # Playwright UI 模式
|
|
|
|
|
|
npm run lint # ESLint 检查
|
2026-02-26 14:00:22 +08:00
|
|
|
|
|
|
|
|
|
|
# 运行单个测试文件
|
|
|
|
|
|
npx vitest src/services/__tests__/auth.service.test.ts
|
|
|
|
|
|
|
|
|
|
|
|
# 运行单个 E2E 测试
|
|
|
|
|
|
npx playwright test auth.spec.ts
|
2026-02-24 18:18:27 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 数据库操作
|
|
|
|
|
|
```bash
|
|
|
|
|
|
cd backend
|
|
|
|
|
|
npx prisma db push # 推送 schema 到数据库 (开发环境)
|
|
|
|
|
|
npx prisma migrate dev # 创建并应用迁移
|
|
|
|
|
|
npx prisma studio # 可视化数据库管理界面
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
## 项目架构
|
|
|
|
|
|
|
|
|
|
|
|
### 后端架构
|
|
|
|
|
|
```
|
|
|
|
|
|
backend/src/
|
|
|
|
|
|
├── index.ts # Express 应用入口,路由挂载
|
|
|
|
|
|
├── controllers/ # 请求处理器 (Auth, Document, Todo, Image)
|
|
|
|
|
|
├── services/ # 业务逻辑层
|
|
|
|
|
|
│ ├── auth.service.ts # 认证逻辑 (注册/登录/验证)
|
|
|
|
|
|
│ ├── password.service.ts # 密码验证和强度检查
|
2026-02-26 14:00:22 +08:00
|
|
|
|
│ ├── ocr.service.ts # OCR 置信度验证和重试逻辑
|
|
|
|
|
|
│ ├── ocr-processor.service.ts # OCR 处理服务 (多 Provider 支持)
|
|
|
|
|
|
│ ├── ocr-providers/ # OCR Provider 实现
|
|
|
|
|
|
│ │ ├── base.provider.ts # 基础接口
|
|
|
|
|
|
│ │ ├── tesseract.provider.ts # Tesseract.js (本地)
|
|
|
|
|
|
│ │ ├── baidu.provider.ts # 百度 OCR (云端)
|
|
|
|
|
|
│ │ └── rapidocr.provider.ts # RapidOCR (本地)
|
2026-02-24 18:18:27 +08:00
|
|
|
|
│ ├── document.service.ts # 文档 CRUD
|
|
|
|
|
|
│ ├── todo.service.ts # 待办事项管理(三态工作流)
|
|
|
|
|
|
│ └── image.service.ts # 图片上传和处理
|
|
|
|
|
|
├── routes/ # API 路由定义
|
2026-02-26 14:00:22 +08:00
|
|
|
|
├── middleware/ # 中间件 (JWT 认证、上传)
|
2026-02-24 18:18:27 +08:00
|
|
|
|
└── lib/prisma.ts # Prisma 客户端单例
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**关键设计模式**:
|
|
|
|
|
|
- **分层架构**: Controller → Service → Prisma (数据层)
|
|
|
|
|
|
- **服务类**: 使用静态方法实现无状态业务逻辑
|
|
|
|
|
|
- **中间件**: JWT 认证中间件保护需要登录的路由
|
2026-02-26 14:00:22 +08:00
|
|
|
|
- **OCR Provider**: 可插拔的 OCR 提供商架构,支持扩展
|
|
|
|
|
|
- **上传中间件**: `upload.middleware.ts` 使用 multer 处理文件上传
|
2026-02-24 18:18:27 +08:00
|
|
|
|
|
|
|
|
|
|
### 前端架构
|
|
|
|
|
|
```
|
|
|
|
|
|
frontend/src/
|
|
|
|
|
|
├── App.tsx # 路由配置,受保护路由包装
|
|
|
|
|
|
├── main.tsx # 应用入口
|
|
|
|
|
|
├── pages/ # 页面组件 (Login, Dashboard, Documents, Todos, Images)
|
|
|
|
|
|
├── components/ # 可复用 UI 组件 (Button, Input, Card, Layout)
|
|
|
|
|
|
├── services/ # API 服务层,与后端通信
|
|
|
|
|
|
│ └── api.ts # Axios 封装,拦截器处理 token
|
|
|
|
|
|
├── hooks/ # React Hooks (useAuth, useDocuments, useTodos, useImages)
|
|
|
|
|
|
├── stores/ # Zustand 状态管理
|
|
|
|
|
|
│ ├── authStore.ts # 认证状态持久化
|
|
|
|
|
|
│ └── uiStore.ts # UI 状态(通知等)
|
|
|
|
|
|
└── types/ # TypeScript 类型定义
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**关键设计模式**:
|
|
|
|
|
|
- **受保护路由**: `<ProtectedRoute>` 组件检查认证状态
|
|
|
|
|
|
- **状态管理**: Zustand 负责全局状态,TanStack Query 负责服务器状态
|
|
|
|
|
|
- **API 客户端**: Axios 拦截器自动添加 JWT token
|
|
|
|
|
|
|
|
|
|
|
|
### 数据模型
|
|
|
|
|
|
核心实体关系:
|
|
|
|
|
|
- **User** 拥有多个 Document, Todo, Image, Category, Tag
|
|
|
|
|
|
- **Document** 可关联多个 Image,可生成多个 Todo
|
|
|
|
|
|
- **Image** 的 `document_id` 可为空(支持 OCR 失败的待处理图片)
|
|
|
|
|
|
- **Todo** 有三种状态: `pending` → `completed` → `confirmed`
|
|
|
|
|
|
|
|
|
|
|
|
## 待办事项三态工作流
|
|
|
|
|
|
|
|
|
|
|
|
待办状态流转是核心业务逻辑:
|
|
|
|
|
|
1. **pending** (未完成) - 新创建的待办,进行中的任务
|
|
|
|
|
|
2. **completed** (已完成) - 用户标记完成,可撤销回 pending
|
|
|
|
|
|
3. **confirmed** (已确认) - 完成后经过确认归档,最终状态
|
|
|
|
|
|
|
|
|
|
|
|
相关 API:
|
|
|
|
|
|
- `PATCH /api/todos/:id/complete` - 标记完成
|
|
|
|
|
|
- `PATCH /api/todos/:id/confirm` - 确认归档
|
|
|
|
|
|
- `PATCH /api/todos/:id/reopen` - 撤销到未完成
|
|
|
|
|
|
|
|
|
|
|
|
## OCR 降级处理
|
|
|
|
|
|
|
|
|
|
|
|
当 OCR 置信度低于阈值 (默认 0.3) 时:
|
|
|
|
|
|
1. 图片保存到数据库,`processing_status = 'failed'`
|
|
|
|
|
|
2. 不自动创建文档
|
|
|
|
|
|
3. 用户可在"待处理图片列表"中手动处理
|
|
|
|
|
|
|
|
|
|
|
|
查询待处理图片:
|
|
|
|
|
|
```sql
|
|
|
|
|
|
SELECT * FROM images
|
|
|
|
|
|
WHERE user_id = ? AND (document_id IS NULL OR processing_status = 'failed')
|
|
|
|
|
|
```
|
|
|
|
|
|
|
2026-02-26 14:00:22 +08:00
|
|
|
|
## OCR 多 Provider 架构
|
|
|
|
|
|
|
|
|
|
|
|
系统支持多种 OCR 提供商,可根据需求选择:
|
|
|
|
|
|
|
|
|
|
|
|
| Provider | 类型 | 速度 | 准确率 | 成本 | 部署要求 |
|
|
|
|
|
|
|----------|------|------|--------|------|----------|
|
|
|
|
|
|
| **tesseract** | 本地 | 慢 | 中 | 免费 | `npm install tesseract.js` |
|
|
|
|
|
|
| **rapidocr** | 本地 | 快 | 高 | 免费 | Docker: `cshgg/rapidocr` |
|
|
|
|
|
|
| **baidu** | 云端 | 快 | 高 | 按次付费 (有免费额度) | 需要 API Key |
|
|
|
|
|
|
|
|
|
|
|
|
### 配置方式
|
|
|
|
|
|
|
|
|
|
|
|
在 `.env` 中设置 `OCR_PROVIDER`:
|
|
|
|
|
|
```bash
|
|
|
|
|
|
# 自动选择可用的 provider (推荐)
|
|
|
|
|
|
OCR_PROVIDER="auto"
|
|
|
|
|
|
|
|
|
|
|
|
# 或指定具体 provider
|
|
|
|
|
|
OCR_PROVIDER="tesseract" # 或 "rapidocr", "baidu"
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 各 Provider 配置
|
|
|
|
|
|
|
|
|
|
|
|
**Tesseract.js** (本地轻量,免费)
|
|
|
|
|
|
```bash
|
|
|
|
|
|
# 安装依赖
|
|
|
|
|
|
npm install tesseract.js
|
|
|
|
|
|
# 无需额外配置
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**RapidOCR** (本地快速准确,推荐)
|
|
|
|
|
|
```bash
|
|
|
|
|
|
# Docker 启动
|
|
|
|
|
|
docker run -d -p 8080:8080 cshgg/rapidocr
|
|
|
|
|
|
|
|
|
|
|
|
# 配置环境变量
|
|
|
|
|
|
RAPIDOCR_API_URL="http://localhost:8080"
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**Baidu OCR** (云端准确,有免费额度)
|
|
|
|
|
|
```bash
|
|
|
|
|
|
# 申请地址: https://cloud.baidu.com/product/ocr
|
|
|
|
|
|
BAIDU_OCR_API_KEY="your_api_key"
|
|
|
|
|
|
BAIDU_OCR_SECRET_KEY="your_secret_key"
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### Provider 架构
|
|
|
|
|
|
|
|
|
|
|
|
OCR Provider 实现位于 `backend/src/services/ocr-providers/`:
|
|
|
|
|
|
- `base.provider.ts` - 基础接口定义
|
|
|
|
|
|
- `tesseract.provider.ts` - Tesseract.js 实现
|
|
|
|
|
|
- `rapidocr.provider.ts` - RapidOCR HTTP API 实现
|
|
|
|
|
|
- `baidu.provider.ts` - 百度 OCR API 实现
|
|
|
|
|
|
|
|
|
|
|
|
新增 Provider 只需继承 `BaseOCRProvider` 并实现 `recognize()` 方法。
|
|
|
|
|
|
|
2026-02-24 18:18:27 +08:00
|
|
|
|
## 测试策略
|
|
|
|
|
|
|
|
|
|
|
|
### 后端测试 (Jest)
|
|
|
|
|
|
- 单元测试覆盖所有 Service 类
|
|
|
|
|
|
- 集成测试验证 API 端点
|
2026-02-26 14:00:22 +08:00
|
|
|
|
- 覆盖率阈值: 80% (branches, functions, lines, statements)
|
|
|
|
|
|
- 测试文件匹配: `**/__tests__/**/*.ts`, `**/?(*.)+(spec|test).ts`
|
2026-02-24 18:18:27 +08:00
|
|
|
|
|
|
|
|
|
|
### 前端测试
|
|
|
|
|
|
- **Vitest**: 组件和服务的单元测试
|
|
|
|
|
|
- **Playwright**: E2E 测试,跨浏览器测试 (Chrome, Firefox, Safari)
|
|
|
|
|
|
- 测试文件位于 `e2e/` 目录
|
2026-02-26 14:00:22 +08:00
|
|
|
|
- E2E 测试配置: 自动启动开发服务器,支持 CI 模式重试
|
2026-02-24 18:18:27 +08:00
|
|
|
|
|
|
|
|
|
|
## API 端点
|
|
|
|
|
|
|
|
|
|
|
|
### 认证
|
|
|
|
|
|
- `POST /api/auth/register` - 用户注册
|
|
|
|
|
|
- `POST /api/auth/login` - 用户登录
|
|
|
|
|
|
|
|
|
|
|
|
### 文档
|
|
|
|
|
|
- `GET /api/documents` - 获取文档列表
|
|
|
|
|
|
- `POST /api/documents` - 创建文档
|
|
|
|
|
|
- `DELETE /api/documents/:id` - 删除文档
|
|
|
|
|
|
|
|
|
|
|
|
### 待办
|
|
|
|
|
|
- `GET /api/todos` - 获取待办列表(支持 status 参数筛选)
|
|
|
|
|
|
- `POST /api/todos` - 创建待办
|
|
|
|
|
|
- `PATCH /api/todos/:id/complete` - 标记完成
|
|
|
|
|
|
- `PATCH /api/todos/:id/confirm` - 确认归档
|
|
|
|
|
|
- `DELETE /api/todos/:id` - 删除待办
|
|
|
|
|
|
|
|
|
|
|
|
### 图片
|
2026-02-26 14:00:22 +08:00
|
|
|
|
- `POST /api/images` - 上传图片
|
|
|
|
|
|
- `GET /api/images` - 获取用户图片列表
|
|
|
|
|
|
- `GET /api/images/pending` - 获取待处理图片 (OCR 失败)
|
|
|
|
|
|
- `GET /api/images/ocr/providers` - 获取可用的 OCR 提供商列表
|
|
|
|
|
|
- `GET /api/images/:id` - 获取单张图片详情
|
|
|
|
|
|
- `POST /api/images/:id/reprocess` - 重新触发 OCR 处理 (支持指定 provider)
|
|
|
|
|
|
- `PUT /api/images/:id/ocr` - 更新 OCR 结果
|
|
|
|
|
|
- `PUT /api/images/:id/link` - 关联图片到文档
|
|
|
|
|
|
- `DELETE /api/images/:id` - 删除图片
|
2026-02-24 18:18:27 +08:00
|
|
|
|
|
|
|
|
|
|
## 环境变量
|
|
|
|
|
|
|
2026-02-26 14:00:22 +08:00
|
|
|
|
后端需要创建 `.env` 文件(参考 `backend/.env.example`):
|
2026-02-24 18:18:27 +08:00
|
|
|
|
```
|
2026-02-26 14:00:22 +08:00
|
|
|
|
# Database
|
2026-02-24 18:18:27 +08:00
|
|
|
|
DATABASE_URL="file:./dev.db"
|
2026-02-26 14:00:22 +08:00
|
|
|
|
|
|
|
|
|
|
# JWT
|
|
|
|
|
|
JWT_SECRET="your-secret-key-change-in-production"
|
|
|
|
|
|
JWT_EXPIRES_IN="24h"
|
|
|
|
|
|
|
|
|
|
|
|
# Server
|
2026-02-24 18:18:27 +08:00
|
|
|
|
PORT=4000
|
2026-02-26 14:00:22 +08:00
|
|
|
|
NODE_ENV="development"
|
|
|
|
|
|
|
|
|
|
|
|
# CORS
|
|
|
|
|
|
CORS_ORIGIN="http://localhost:3000"
|
|
|
|
|
|
|
|
|
|
|
|
# OCR Provider: tesseract | baidu | rapidocr | auto
|
|
|
|
|
|
OCR_PROVIDER="auto"
|
|
|
|
|
|
OCR_CONFIDENCE_THRESHOLD="0.3"
|
|
|
|
|
|
|
|
|
|
|
|
# Tesseract.js (本地 OCR)
|
|
|
|
|
|
# 安装: npm install tesseract.js
|
|
|
|
|
|
|
|
|
|
|
|
# Baidu OCR (云端 OCR)
|
|
|
|
|
|
BAIDU_OCR_API_KEY=""
|
|
|
|
|
|
BAIDU_OCR_SECRET_KEY=""
|
|
|
|
|
|
|
|
|
|
|
|
# RapidOCR (本地快速 OCR)
|
|
|
|
|
|
RAPIDOCR_API_URL="http://localhost:8080"
|
|
|
|
|
|
|
|
|
|
|
|
# AI (GLM)
|
|
|
|
|
|
GLM_API_KEY=""
|
|
|
|
|
|
GLM_API_URL="https://open.bigmodel.cn/api/paas/v4/chat/completions"
|
|
|
|
|
|
GLM_MODEL="glm-4-flash"
|
|
|
|
|
|
|
|
|
|
|
|
# AI (MiniMax)
|
|
|
|
|
|
MINIMAX_API_KEY=""
|
|
|
|
|
|
MINIMAX_API_URL="https://api.minimax.chat/v1/chat/completions"
|
|
|
|
|
|
MINIMAX_MODEL="abab6.5s-chat"
|
|
|
|
|
|
|
|
|
|
|
|
# AI (DeepSeek)
|
|
|
|
|
|
DEEPSEEK_API_KEY=""
|
|
|
|
|
|
DEEPSEEK_API_URL="https://api.deepseek.com/v1/chat/completions"
|
|
|
|
|
|
DEEPSEEK_MODEL="deepseek-chat"
|
|
|
|
|
|
|
|
|
|
|
|
# Upload
|
|
|
|
|
|
UPLOAD_MAX_SIZE="10485760"
|
|
|
|
|
|
UPLOAD_ALLOWED_TYPES="image/jpeg,image/png,image/webp"
|
2026-02-24 18:18:27 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
## 测试账号
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
用户名: testuser
|
|
|
|
|
|
密码: Password123@
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
## 当前开发状态
|
|
|
|
|
|
|
|
|
|
|
|
已完成功能:
|
|
|
|
|
|
- ✅ 用户认证系统 (JWT)
|
|
|
|
|
|
- ✅ 文档 CRUD
|
|
|
|
|
|
- ✅ 待办三态工作流
|
|
|
|
|
|
- ✅ 图片上传和 OCR 状态追踪
|
2026-02-26 14:00:22 +08:00
|
|
|
|
- ✅ 多 Provider OCR 架构 (Tesseract.js / Baidu / RapidOCR)
|
2026-02-24 18:18:27 +08:00
|
|
|
|
- ✅ 前后端单元测试 (148 个测试全部通过)
|
|
|
|
|
|
- ✅ E2E 测试框架
|
|
|
|
|
|
|
|
|
|
|
|
待开发功能 (P1 优先级):
|
|
|
|
|
|
- ⏳ AI 分析功能 (GLM/MiniMax/DeepSeek)
|
|
|
|
|
|
- ⏳ 图片-文档-待办关联增强
|
2026-02-26 14:00:22 +08:00
|
|
|
|
- ⏳ 前端 OCR 设置页面 (Provider 选择和测试)
|