一个简单易用的本地发票管理系统,支持批量解析和管理电子发票。
- PDF 发票(文字提取)
- 图片发票:PNG / JPG / JPEG / BMP / GIF(OCR识别)
- 📁 批量上传发票(支持文件夹选择)
- 📊 按月份自动归类,显示统计数据
- 🏢 购买方分类筛选
- 📥 下载月度/全部发票ZIP包
- 🌗 亮色/暗色主题切换
- 🔍 发票预览(iframe方式)
⚠️ 重复文件自动检测- 🎯 左下角3D水晶计数器(显示使用次数)
pip install -r requirements.txt主要依赖:
- FastAPI
- pdfplumber
- rapidocr-onnxruntime
- Pillow
python -m uvicorn main:app --host 0.0.0.0 --port 8000打开浏览器访问 http://localhost:8000/local
- 点击上传区域或拖拽文件
- 支持多选文件(Ctrl/Cmd+点击)
- 系统自动解析所有支持格式的文件
- 顶部显示发票总数、其他发票数、总金额
- 如果有多个购买方,显示购买方筛选按钮
- 点击月份卡片展开查看该月发票列表
- 每个月份卡片下方有"下载月度发票原件ZIP"按钮
- 底部有"下载全部发票"按钮
- ZIP文件按月份分文件夹存储
系统会尝试提取以下信息:
- 日期:从"2026年01月31日"格式提取
- 购方:第一个"名称:"后的内容
- 销方:第二个"名称:"后的内容
- 金额:从"小写 ¥123.45"格式提取
- 发票号:20位数字
某些PDF使用特殊Unicode字符(如Kangxi radicals),系统会自动转换:
- ⽂ → 文(U+2F42 → U+6587)
- ⽉ → 月(U+2F49 → U+6708)
- ⽇ → 日(U+2F47 → U+65E5)
这确保相同公司的发票能正确归类。
系统通过两种方式检测重复:
- 文件名重复:相同文件名的文件会被跳过
- 内容重复:相同内容(MD5哈希)的文件会被跳过
重复文件会弹窗提示,不会计入统计数据。
- 上传的发票文件会临时存储在服务器
- 每次上传生成唯一会话ID
- 关闭浏览器后文件会被清理
- 不同会话之间数据不共享
fapiao/
├── main.py # FastAPI主程序
├── routes/
│ ├── __init__.py
│ ├── local_invoice.py # 发票解析API
│ └── utils.py # 工具函数
├── services/
│ ├── __init__.py
│ └── invoice_parser.py # 发票解析服务
├── static/
│ ├── index.html # 前端页面
│ ├── css/style.css # 样式
│ ├── js/
│ │ ├── app.js # 主JavaScript
│ │ └── crystal-counter.js # 3D计数器效果
│ └── images/fapiao.png # 网站图标
├── data/ # 数据目录(需手动创建)
│ └── counter.json # 使用计数器数据
├── _sample/ # 示例发票文件
├── requirements.txt # Python依赖
└── README.md # 本文档
# 拉取最新代码
git pull
# 重启服务
pm2 restart fapiao
# 查看日志
pm2 logs fapiao首次部署时需要手动创建计数器数据文件:
# 创建 data 目录
mkdir -p data
# 创建计数器文件(初始值为0)
echo '{"count": 0}' > data/counter.json
# 确保目录和文件有正确的权限
chmod 755 data
chmod 644 data/counter.json注意:data/counter.json 已被 .gitignore 忽略,不会被提交到 GitHub。每个部署环境需要单独初始化。
如果使用 Nginx 反向代理,确保添加 WebSocket 支持:
location / {
proxy_pass http://127.0.0.1:8000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}fapiao/ ├── main.py # FastAPI主程序 ├── routes/ │ ├── init.py │ ├── local_invoice.py # 发票解析API │ └── utils.py # 工具函数 ├── services/ │ ├── init.py │ └── invoice_parser.py # 发票解析服务 ├── static/ │ ├── index.html # 前端页面 │ ├── css/style.css # 样式 │ ├── js/app.js # JavaScript │ └── images/fapiao.png # 网站图标 ├── _sample/ # 示例发票文件 ├── requirements.txt # Python依赖 └── README.md # 本文档
## 技术栈
- **后端**:FastAPI + pdfplumber + rapidocr
- **前端**:纯HTML/JavaScript
- **PDF处理**:pdfplumber(文字提取)
- **OCR**:rapidocr-onnxruntime(图片识别)
## 常见问题
### Q: 为什么有些发票解析失败?
A: 可能原因:
- 发票格式不在支持范围内
- 图片质量太低,OCR无法识别
- 发票使用了特殊字体或布局
### Q: 为什么购买方显示"未知"?
A: 发票可能没有标准格式的购买方信息,系统无法提取。
### Q: 下载的ZIP文件在哪里?
A: 浏览器默认下载到"下载"文件夹,文件名格式为"年份-金额总数.zip"。
### Q: 支持哪些浏览器?
A: 推荐使用Chrome、Edge、Firefox等现代浏览器,需要支持ES6+和File API。
## 许可证
MIT License