feat: Web 表格编辑、易耗品出库单自动生成与文档完善
- 新增 fill_consumable_doc,根据 CSV 填写 Word 出库单(宋体五号) - Web 处理完成后自动生成出库单并提供下载 - 前端拆分为 static 资源,支持在线编辑 CSV 与分步提交财务系统 - 补充 API.md、README(含 Mermaid 数据流)及 config.example.json Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
463
API.md
Normal file
463
API.md
Normal file
@@ -0,0 +1,463 @@
|
||||
# 财务报销自动化 — API 文档
|
||||
|
||||
> 基础地址: `http://localhost:5000`
|
||||
> 启动: `python web/app.py`
|
||||
|
||||
## 总览
|
||||
|
||||
| # | 方法 | 路径 | 说明 |
|
||||
|---|------|------|------|
|
||||
| 1 | GET | `/` | PC 端主页 |
|
||||
| 2 | POST | `/api/session` | 创建会话 |
|
||||
| 3 | POST | `/api/upload/<session_id>` | 上传文件(PDF/图片) |
|
||||
| 4 | POST | `/api/upload-csv/<session_id>` | 上传 CSV 发票数据 |
|
||||
| 5 | GET | `/api/files/<session_id>` | 列出会话目录中的文件 |
|
||||
| 6 | POST | `/api/process/<session_id>` | 启动处理(提取+OCR+出库单) |
|
||||
| 7 | GET | `/api/logs/<session_id>` | SSE 日志流 |
|
||||
| 8 | GET | `/api/download/<session_id>/<filename>` | 下载生成的文件 |
|
||||
| 9 | GET | `/api/data/<session_id>` | 获取发票数据(JSON) |
|
||||
| 10 | POST | `/api/save/<session_id>` | 保存编辑后的发票数据 |
|
||||
| 11 | POST | `/api/submit-financial/<session_id>` | 提交到财务系统 |
|
||||
| 12 | GET | `/mobile/<session_id>` | 移动端上传页面 |
|
||||
| 13 | POST | `/api/mobile-upload/<session_id>` | 移动端上传图片 |
|
||||
|
||||
---
|
||||
|
||||
## 会话与目录
|
||||
|
||||
- 调用 `POST /api/session` 获得 `session_id`
|
||||
- 该会话下所有文件存放在 `web/uploads/<session_id>/`
|
||||
- 典型产物:`invoice_summary.csv`、`invoice_summary.md`、`易耗品、出库单.doc`、`config.json`、`session.log`、`result.json`
|
||||
|
||||
---
|
||||
|
||||
## 接口详情
|
||||
|
||||
### 1. 创建会话
|
||||
|
||||
```
|
||||
POST /api/session
|
||||
```
|
||||
|
||||
**响应:**
|
||||
|
||||
```json
|
||||
{ "session_id": "a1b2c3d4e5f6" }
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 2. 上传文件(PDF/图片)
|
||||
|
||||
```
|
||||
POST /api/upload/<session_id>
|
||||
Content-Type: multipart/form-data
|
||||
```
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| file | File | PDF 发票或支付截图 |
|
||||
|
||||
**响应(成功):**
|
||||
|
||||
```json
|
||||
{ "ok": true, "filename": "1. 电容一批.pdf" }
|
||||
```
|
||||
|
||||
**响应(失败):**
|
||||
|
||||
```json
|
||||
{ "error": "未选择文件" }
|
||||
```
|
||||
|
||||
HTTP `400`
|
||||
|
||||
---
|
||||
|
||||
### 3. 上传 CSV 发票数据
|
||||
|
||||
```
|
||||
POST /api/upload-csv/<session_id>
|
||||
Content-Type: multipart/form-data
|
||||
```
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| file | File | 发票汇总 CSV |
|
||||
|
||||
**响应(成功):**
|
||||
|
||||
```json
|
||||
{ "ok": true, "filename": "invoice_summary.csv" }
|
||||
```
|
||||
|
||||
> 上传 CSV 后可跳过 PDF 提取和 OCR,直接进入处理/编辑流程。
|
||||
|
||||
---
|
||||
|
||||
### 4. 列出会话文件
|
||||
|
||||
```
|
||||
GET /api/files/<session_id>
|
||||
```
|
||||
|
||||
**响应:**
|
||||
|
||||
```json
|
||||
{
|
||||
"pdfs": ["1. 电容一批.pdf"],
|
||||
"images": ["payment_01.jpg"]
|
||||
}
|
||||
```
|
||||
|
||||
`images` 包含扩展名:`.png`、`.jpg`、`.jpeg`、`.bmp`、`.webp`。
|
||||
|
||||
---
|
||||
|
||||
### 5. 启动管道处理
|
||||
|
||||
```
|
||||
POST /api/process/<session_id>
|
||||
Content-Type: application/json
|
||||
```
|
||||
|
||||
**请求体:**
|
||||
|
||||
| 字段 | 类型 | 必填 | 说明 |
|
||||
|------|------|------|------|
|
||||
| mode | string | 否 | `"pdf"` / `"csv"` / `"auto"`(默认 `auto`) |
|
||||
| username | string | 否 | 财务系统工号 |
|
||||
| password | string | 否 | 登录密码 |
|
||||
| default_name | string | 否 | 默认报销人姓名 |
|
||||
| default_card_no | string | 否 | 默认公务卡号 |
|
||||
| default_person_id | string | 否 | 默认人员编号 |
|
||||
| consumable_storage | string | 否 | 出库单存放地点;未填则用 `config.json` 中的值 |
|
||||
|
||||
**mode 行为:**
|
||||
|
||||
| mode | 行为 |
|
||||
|------|------|
|
||||
| `auto` | 仅有 CSV、无 PDF → CSV 模式;否则 → PDF 提取 + OCR |
|
||||
| `csv` | 使用已上传 CSV,跳过提取与 OCR |
|
||||
| `pdf` | 执行 PDF 提取 + OCR |
|
||||
|
||||
**处理内容(PDF 模式):**
|
||||
|
||||
1. 从会话目录 PDF 提取发票信息 → `invoice_summary.csv` / `.md`
|
||||
2. 对支付截图 OCR,回填刷卡字段
|
||||
3. 从项目根目录复制 `易耗品、出库单.doc` 模板到会话目录并自动填写(需 Windows + Word)
|
||||
|
||||
配置会写入 `web/uploads/<session_id>/config.json`。
|
||||
|
||||
**响应(立即):**
|
||||
|
||||
```json
|
||||
{ "status": "started" }
|
||||
```
|
||||
|
||||
处理在后台线程执行,进度与结果通过 `GET /api/logs/<session_id>`(SSE)获取。
|
||||
|
||||
**SSE 完成时 `result` 示例(成功):**
|
||||
|
||||
```json
|
||||
{
|
||||
"ok": true,
|
||||
"elapsed": "45.2s",
|
||||
"invoice_count": 4,
|
||||
"csv_url": "/api/download/<session_id>/invoice_summary.csv",
|
||||
"md_url": "/api/download/<session_id>/invoice_summary.md",
|
||||
"doc_url": "/api/download/<session_id>/%E6%98%93%E8%80%97%E5%93%81%E3%80%81%E5%87%BA%E5%BA%93%E5%8D%95.doc",
|
||||
"doc_ok": true
|
||||
}
|
||||
```
|
||||
|
||||
**出库单生成失败时(CSV 等仍可能成功):**
|
||||
|
||||
```json
|
||||
{
|
||||
"ok": true,
|
||||
"invoice_count": 4,
|
||||
"csv_url": "/api/download/<session_id>/invoice_summary.csv",
|
||||
"doc_ok": false,
|
||||
"doc_error": "服务器未安装 pywin32,无法生成 Word 出库单"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 6. SSE 日志流
|
||||
|
||||
```
|
||||
GET /api/logs/<session_id>
|
||||
Accept: text/event-stream
|
||||
```
|
||||
|
||||
**日志行格式:**
|
||||
|
||||
```
|
||||
data: 2026-05-26 12:00:01 [INFO ] extractor: 正在提取发票...
|
||||
```
|
||||
|
||||
**结束消息:**
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "done",
|
||||
"result": { }
|
||||
}
|
||||
```
|
||||
|
||||
`result` 结构取决于触发来源:
|
||||
|
||||
| 来源 | 典型字段 |
|
||||
|------|----------|
|
||||
| `/api/process` | `ok`, `elapsed`, `invoice_count`, `csv_url`, `md_url`, `doc_url`, `doc_ok`, `doc_error` |
|
||||
| `/api/submit-financial` | `ok`, `submit_ok`, `submit_error` |
|
||||
|
||||
---
|
||||
|
||||
### 7. 下载文件
|
||||
|
||||
```
|
||||
GET /api/download/<session_id>/<filename>
|
||||
```
|
||||
|
||||
**响应:** 文件二进制流,带 `Content-Disposition: attachment` 与 UTF-8 文件名。
|
||||
|
||||
| 扩展名 | Content-Type |
|
||||
|--------|----------------|
|
||||
| `.csv` | `text/csv; charset=utf-8` |
|
||||
| `.md` | `text/markdown; charset=utf-8` |
|
||||
| `.doc` | `application/msword` |
|
||||
| 其它 | `application/octet-stream` |
|
||||
|
||||
**常见文件名:**
|
||||
|
||||
| 文件名 | 说明 |
|
||||
|--------|------|
|
||||
| `invoice_summary.csv` | 发票汇总(含 OCR 结果) |
|
||||
| `invoice_summary.md` | Markdown 摘要 |
|
||||
| `易耗品、出库单.doc` | 自动填写的出库单 |
|
||||
| 用户上传的 CSV 名 | CSV 快捷模式下的原始文件 |
|
||||
|
||||
**错误:**
|
||||
|
||||
```json
|
||||
{ "error": "文件不存在" }
|
||||
```
|
||||
|
||||
HTTP `404`。`filename` 仅允许会话目录内的文件名(防止路径穿越)。
|
||||
|
||||
---
|
||||
|
||||
### 8. 获取发票数据
|
||||
|
||||
```
|
||||
GET /api/data/<session_id>
|
||||
```
|
||||
|
||||
**响应:**
|
||||
|
||||
```json
|
||||
{
|
||||
"csv_filename": "invoice_summary.csv",
|
||||
"fields": [
|
||||
"序号", "发票号码", "开票日期", "项目名称", "规格型号",
|
||||
"价税合计", "销售方名称", "人员姓名", "刷卡日期",
|
||||
"公务卡号", "刷卡金额", "备注", "工号"
|
||||
],
|
||||
"data": [
|
||||
{
|
||||
"__row": 0,
|
||||
"序号": "1",
|
||||
"发票号码": "26442000005432755951",
|
||||
"价税合计": "2900.00"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
- `fields`:列顺序
|
||||
- `data[].__row`:内部行索引(保存时不需要提交,服务端按数组顺序写回)
|
||||
|
||||
**错误:** `404` 未找到 CSV;`500` 读取失败。
|
||||
|
||||
---
|
||||
|
||||
### 9. 保存编辑后的发票数据
|
||||
|
||||
```
|
||||
POST /api/save/<session_id>
|
||||
Content-Type: application/json
|
||||
```
|
||||
|
||||
**请求体:**
|
||||
|
||||
```json
|
||||
{
|
||||
"csv_filename": "invoice_summary.csv",
|
||||
"data": [
|
||||
{
|
||||
"序号": "1",
|
||||
"发票号码": "26442000005432755951",
|
||||
"开票日期": "2026/05/18",
|
||||
"项目名称": "...",
|
||||
"规格型号": "...",
|
||||
"价税合计": "2900.00",
|
||||
"销售方名称": "...",
|
||||
"人员姓名": "",
|
||||
"刷卡日期": "2026/04/28",
|
||||
"公务卡号": "",
|
||||
"刷卡金额": "2850.00",
|
||||
"备注": "",
|
||||
"工号": "202407021"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
**响应(成功):**
|
||||
|
||||
```json
|
||||
{
|
||||
"ok": true,
|
||||
"doc_ok": true,
|
||||
"doc_url": "/api/download/<session_id>/%E6%98%93%E8%80%97%E5%93%81%E3%80%81%E5%87%BA%E5%BA%93%E5%8D%95.doc"
|
||||
}
|
||||
```
|
||||
|
||||
保存后会根据最新 CSV **重新生成** 出库单 Word(与会话 `config.json` 中的 `consumable_storage` 等配置一致)。
|
||||
|
||||
若出库单生成失败:
|
||||
|
||||
```json
|
||||
{
|
||||
"ok": true,
|
||||
"doc_ok": false,
|
||||
"doc_error": "出库单模板不存在,请将模板放在项目根目录"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 10. 提交到财务系统
|
||||
|
||||
```
|
||||
POST /api/submit-financial/<session_id>
|
||||
```
|
||||
|
||||
**前置条件:**
|
||||
|
||||
- 会话目录存在 `config.json`(由 `/api/process` 写入)
|
||||
- 存在可用的发票 CSV(通常为 `invoice_summary.csv`)
|
||||
|
||||
**说明:** 前端一般在提交前调用 `/api/save` 保存表格修改。本接口**不会**自动执行发票提取或 OCR。
|
||||
|
||||
**响应(立即):**
|
||||
|
||||
```json
|
||||
{ "status": "started" }
|
||||
```
|
||||
|
||||
**SSE 完成示例:**
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "done",
|
||||
"result": {
|
||||
"ok": true,
|
||||
"submit_ok": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
失败时 `submit_ok: false`,`submit_error` 为错误描述。
|
||||
|
||||
---
|
||||
|
||||
### 11. 移动端上传页面
|
||||
|
||||
```
|
||||
GET /mobile/<session_id>
|
||||
```
|
||||
|
||||
返回移动端 HTML 页面。扫码上传的图片与 PC 端共用同一会话目录;PC 通过轮询 `GET /api/files/<session_id>` 同步文件列表。
|
||||
|
||||
---
|
||||
|
||||
### 12. 移动端上传图片
|
||||
|
||||
```
|
||||
POST /api/mobile-upload/<session_id>
|
||||
Content-Type: multipart/form-data
|
||||
```
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| file | File | 图片文件 |
|
||||
|
||||
逻辑与 `POST /api/upload/<session_id>` 相同。
|
||||
|
||||
---
|
||||
|
||||
## 错误码汇总
|
||||
|
||||
| HTTP | 场景 |
|
||||
|------|------|
|
||||
| 400 | 参数缺失、未找到配置等 |
|
||||
| 404 | `session_id` 不存在、文件不存在 |
|
||||
| 500 | CSV 读取失败等内部错误 |
|
||||
|
||||
统一错误体:
|
||||
|
||||
```json
|
||||
{ "error": "错误描述" }
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 端到端流程
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant PC as PC 端
|
||||
participant Server as Server
|
||||
participant Mobile as 移动端
|
||||
participant Word as Word COM
|
||||
|
||||
PC->>Server: POST /api/session
|
||||
Server-->>PC: session_id
|
||||
|
||||
PC->>Server: POST /api/upload/{sid}
|
||||
PC->>Server: POST /api/process/{sid}
|
||||
Note over Server: PDF 提取 + OCR + 写 config.json
|
||||
Server->>Word: 复制模板并填写出库单
|
||||
Server-->>PC: SSE done (csv_url, doc_url, ...)
|
||||
|
||||
PC->>Server: GET /api/data/{sid}
|
||||
Server-->>PC: fields + data
|
||||
PC->>Server: POST /api/save/{sid}
|
||||
Note over Server: 更新 CSV,重新生成出库单
|
||||
Server-->>PC: doc_url
|
||||
|
||||
PC->>Server: GET /api/download/{sid}/易耗品、出库单.doc
|
||||
|
||||
PC->>Server: POST /api/submit-financial/{sid}
|
||||
Note over Server: Playwright 浏览器填报
|
||||
Server-->>PC: SSE done (submit_ok)
|
||||
|
||||
Mobile->>Server: POST /api/mobile-upload/{sid}
|
||||
PC->>Server: GET /api/files/{sid} (轮询)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 相关 CLI
|
||||
|
||||
不经过 Web、在本地直接填写出库单:
|
||||
|
||||
```bash
|
||||
python -m app.fill_consumable_doc --csv invoice_summary.csv --doc "易耗品、出库单.doc"
|
||||
```
|
||||
|
||||
详见 [README.md](./README.md)。
|
||||
Reference in New Issue
Block a user