From a72c4ffaab61c03bbf7ecc65e240f48709441b0b Mon Sep 17 00:00:00 2001 From: wandering Date: Tue, 26 May 2026 14:17:26 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20Web=20=E8=A1=A8=E6=A0=BC=E7=BC=96?= =?UTF-8?q?=E8=BE=91=E3=80=81=E6=98=93=E8=80=97=E5=93=81=E5=87=BA=E5=BA=93?= =?UTF-8?q?=E5=8D=95=E8=87=AA=E5=8A=A8=E7=94=9F=E6=88=90=E4=B8=8E=E6=96=87?= =?UTF-8?q?=E6=A1=A3=E5=AE=8C=E5=96=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 fill_consumable_doc,根据 CSV 填写 Word 出库单(宋体五号) - Web 处理完成后自动生成出库单并提供下载 - 前端拆分为 static 资源,支持在线编辑 CSV 与分步提交财务系统 - 补充 API.md、README(含 Mermaid 数据流)及 config.example.json Co-authored-by: Cursor --- .gitignore | 4 + API.md | 463 +++++++++++++++++++++++++++++++++ README.md | 182 ++++++++----- app/bot.py | 20 +- app/config.py | 1 + app/fill_consumable_doc.py | 243 +++++++++++++++++ config.example.json | 12 + web/app.py | 288 ++++++++++++++++++--- web/static/css/index.css | 24 ++ web/static/js/index.js | 517 +++++++++++++++++++++++++++++++++++++ web/templates/index.html | 362 +++----------------------- 易耗品、出库单.doc | Bin 0 -> 122368 bytes 12 files changed, 1674 insertions(+), 442 deletions(-) create mode 100644 API.md create mode 100644 app/fill_consumable_doc.py create mode 100644 config.example.json create mode 100644 web/static/css/index.css create mode 100644 web/static/js/index.js create mode 100644 易耗品、出库单.doc diff --git a/.gitignore b/.gitignore index e2296db..b14367e 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,10 @@ build/ # Playwright MCP snapshots .playwright-mcp/ +# Local secrets & backups +config.json +*.doc.bak + # Uploads (user data) web/uploads/ diff --git a/API.md b/API.md new file mode 100644 index 0000000..75c9a06 --- /dev/null +++ b/API.md @@ -0,0 +1,463 @@ +# 财务报销自动化 — API 文档 + +> 基础地址: `http://localhost:5000` +> 启动: `python web/app.py` + +## 总览 + +| # | 方法 | 路径 | 说明 | +|---|------|------|------| +| 1 | GET | `/` | PC 端主页 | +| 2 | POST | `/api/session` | 创建会话 | +| 3 | POST | `/api/upload/` | 上传文件(PDF/图片) | +| 4 | POST | `/api/upload-csv/` | 上传 CSV 发票数据 | +| 5 | GET | `/api/files/` | 列出会话目录中的文件 | +| 6 | POST | `/api/process/` | 启动处理(提取+OCR+出库单) | +| 7 | GET | `/api/logs/` | SSE 日志流 | +| 8 | GET | `/api/download//` | 下载生成的文件 | +| 9 | GET | `/api/data/` | 获取发票数据(JSON) | +| 10 | POST | `/api/save/` | 保存编辑后的发票数据 | +| 11 | POST | `/api/submit-financial/` | 提交到财务系统 | +| 12 | GET | `/mobile/` | 移动端上传页面 | +| 13 | POST | `/api/mobile-upload/` | 移动端上传图片 | + +--- + +## 会话与目录 + +- 调用 `POST /api/session` 获得 `session_id` +- 该会话下所有文件存放在 `web/uploads//` +- 典型产物:`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/ +Content-Type: multipart/form-data +``` + +| 字段 | 类型 | 说明 | +|------|------|------| +| file | File | PDF 发票或支付截图 | + +**响应(成功):** + +```json +{ "ok": true, "filename": "1. 电容一批.pdf" } +``` + +**响应(失败):** + +```json +{ "error": "未选择文件" } +``` + +HTTP `400` + +--- + +### 3. 上传 CSV 发票数据 + +``` +POST /api/upload-csv/ +Content-Type: multipart/form-data +``` + +| 字段 | 类型 | 说明 | +|------|------|------| +| file | File | 发票汇总 CSV | + +**响应(成功):** + +```json +{ "ok": true, "filename": "invoice_summary.csv" } +``` + +> 上传 CSV 后可跳过 PDF 提取和 OCR,直接进入处理/编辑流程。 + +--- + +### 4. 列出会话文件 + +``` +GET /api/files/ +``` + +**响应:** + +```json +{ + "pdfs": ["1. 电容一批.pdf"], + "images": ["payment_01.jpg"] +} +``` + +`images` 包含扩展名:`.png`、`.jpg`、`.jpeg`、`.bmp`、`.webp`。 + +--- + +### 5. 启动管道处理 + +``` +POST /api/process/ +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//config.json`。 + +**响应(立即):** + +```json +{ "status": "started" } +``` + +处理在后台线程执行,进度与结果通过 `GET /api/logs/`(SSE)获取。 + +**SSE 完成时 `result` 示例(成功):** + +```json +{ + "ok": true, + "elapsed": "45.2s", + "invoice_count": 4, + "csv_url": "/api/download//invoice_summary.csv", + "md_url": "/api/download//invoice_summary.md", + "doc_url": "/api/download//%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//invoice_summary.csv", + "doc_ok": false, + "doc_error": "服务器未安装 pywin32,无法生成 Word 出库单" +} +``` + +--- + +### 6. SSE 日志流 + +``` +GET /api/logs/ +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// +``` + +**响应:** 文件二进制流,带 `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/ +``` + +**响应:** + +```json +{ + "csv_filename": "invoice_summary.csv", + "fields": [ + "序号", "发票号码", "开票日期", "项目名称", "规格型号", + "价税合计", "销售方名称", "人员姓名", "刷卡日期", + "公务卡号", "刷卡金额", "备注", "工号" + ], + "data": [ + { + "__row": 0, + "序号": "1", + "发票号码": "26442000005432755951", + "价税合计": "2900.00" + } + ] +} +``` + +- `fields`:列顺序 +- `data[].__row`:内部行索引(保存时不需要提交,服务端按数组顺序写回) + +**错误:** `404` 未找到 CSV;`500` 读取失败。 + +--- + +### 9. 保存编辑后的发票数据 + +``` +POST /api/save/ +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//%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/ +``` + +**前置条件:** + +- 会话目录存在 `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/ +``` + +返回移动端 HTML 页面。扫码上传的图片与 PC 端共用同一会话目录;PC 通过轮询 `GET /api/files/` 同步文件列表。 + +--- + +### 12. 移动端上传图片 + +``` +POST /api/mobile-upload/ +Content-Type: multipart/form-data +``` + +| 字段 | 类型 | 说明 | +|------|------|------| +| file | File | 图片文件 | + +逻辑与 `POST /api/upload/` 相同。 + +--- + +## 错误码汇总 + +| 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)。 diff --git a/README.md b/README.md index 27aa6f3..28b3972 100644 --- a/README.md +++ b/README.md @@ -1,74 +1,85 @@ # 财务报销自动化 -自动从 PDF 发票提取信息,OCR 识别支付记录截图,然后在财务系统中自动填报报销单。 +自动从 PDF 发票提取信息,OCR 识别支付记录截图,生成发票汇总表与易耗品出库单,并可选在财务系统中自动填报报销单。 ## 项目结构 ``` -├── run.py # CLI 入口 -├── config.json # 配置文件(登录凭据、系统 URL 等) +├── run.py # CLI 入口(发票提取 → OCR → 浏览器填报) +├── config.json # 配置文件(登录凭据、默认值、存放地点等) +├── 易耗品、出库单.doc # 易耗品出库单 Word 模板(Web/CLI 填写用) ├── app/ -│ ├── config.py # 配置加载 -│ ├── extractor.py # PDF 发票信息提取 -│ ├── ocr.py # OCR 刷卡信息识别 -│ ├── bot.py # 浏览器自动填报 -│ └── pipeline.py # 流程编排(数据在内存中流转) +│ ├── config.py # 配置加载 +│ ├── extractor.py # PDF 发票信息提取 +│ ├── ocr.py # OCR 刷卡信息识别 +│ ├── bot.py # 浏览器自动填报 +│ ├── pipeline.py # CLI 流程编排 +│ └── fill_consumable_doc.py # 将 CSV 填入易耗品出库单(Word COM) ├── web/ -│ ├── app.py # Web 服务入口 +│ ├── app.py # Web 服务入口 │ ├── templates/ -│ │ ├── index.html # Web 前端页面 -│ │ └── mobile_upload.html # 移动端扫码上传页面 -│ └── uploads/ # 用户上传文件目录 -├── *.pdf # 发票 PDF(按需放置) -├── *.png / *.jpg # 与 PDF 同名的支付截图 -├── invoice_summary.csv # 中间产物 — 发票汇总表 -└── images/ # 调试截图 +│ │ ├── index.html # PC 端主页 +│ │ └── mobile_upload.html # 移动端扫码上传 +│ ├── static/ # 前端 CSS / JS +│ └── uploads/ # 按会话隔离的上传与产物目录 +├── *.pdf # 发票 PDF(CLI 模式,放在项目根目录) +├── *.png / *.jpg # 与 PDF 配对的支付截图 +├── invoice_summary.csv # 发票汇总表(CLI 产物) +└── images/ # 浏览器调试截图 ``` ## 数据流 -``` -PDF 文件 ──► extractor 提取 ──► 发票列表 - │ -支付截图 ──► OCR 识别 ────────────► 回填刷卡信息 - │ - invoice_summary.csv - │ - bot 打开浏览器 ──► 自动填报 +```mermaid +flowchart TB + PDF[PDF 发票] --> Extract[extractor 提取] + Extract --> List[发票列表] + Img[支付截图] --> OCR[OCR 识别] + List --> OCR + OCR --> CSV[(invoice_summary.csv)] + CSV --> Fill[fill_consumable_doc] + Fill --> Doc[易耗品、出库单.doc] + CSV --> Bot[bot 浏览器自动化] + Bot --> Submit[财务系统填报
可选] ``` ## 环境要求 - Python 3.10+ -- 依赖见下方安装步骤 +- Windows(易耗品出库单填写依赖 Microsoft Word + COM,仅 Windows 可用) +- 主要依赖见下方安装步骤 ## 快速开始 ### 1. 安装依赖 -> 以下依赖需在 MinerU 虚拟环境中安装: -> ```bash -> conda activate MinerU -> ``` +> OCR 相关依赖建议在已有 PaddleOCR 的环境中安装(如 MinerU 虚拟环境)。 ```bash -pip install pdfplumber==0.11.9 paddleocr==2.8.1 playwright==1.60.0 flask==3.0.3 +pip install pdfplumber==0.11.9 paddleocr==2.8.1 playwright==1.60.0 flask==3.0.3 pywin32 playwright install chromium ``` -### 2. 准备数据 +| 依赖 | 用途 | +|------|------| +| pdfplumber | PDF 发票文本提取 | +| paddleocr | 支付截图 OCR | +| playwright | 财务系统浏览器自动化 | +| flask | Web 服务 | +| pywin32 | 填写 Word 出库单(`fill_consumable_doc`) | + +### 2. 准备数据(CLI 模式) 将发票 PDF 和对应的支付截图放在项目根目录下。脚本会自动匹配 PDF 与截图: 1. **优先文件名匹配** — PDF 与截图同名(如 `发票.pdf` ↔ `发票.png`) -2. **金额近邻匹配** — 文件名不同时,自动提取 PDF 的价税合计和截图的刷卡金额进行配对 +2. **金额近邻匹配** — 文件名不同时,按价税合计与刷卡金额就近配对 截图支持格式:`.png`、`.jpg`、`.jpeg`、`.bmp`、`.webp`。 -``` ### 3. 配置 -编辑 `config.json`,填写登录凭据和默认值: +编辑 `config.json`: ```json { @@ -76,13 +87,21 @@ playwright install chromium "password": "你的密码", "default_name": "默认报销人姓名", "default_card_no": "默认公务卡号", - "default_person_id": "默认人员编号" + "default_person_id": "默认人员编号", + "consumable_storage": "躬行楼 C205" } ``` -未填写的字段将使用默认值,URL 类配置一般无需修改。 +| 字段 | 说明 | +|------|------| +| `username` / `password` | 信息门户登录凭据 | +| `default_name` | 默认报销人姓名 | +| `default_card_no` | 默认公务卡号 | +| `default_person_id` | 默认人员编号(工号) | +| `consumable_storage` | 出库单「存放地点」列默认值 | +| `sso_login_url` 等 | 系统 URL,一般无需修改 | -### 4. 运行 +### 4. 运行(CLI) ```bash # 全流程(发票提取 → OCR 识别 → 浏览器填报) @@ -97,52 +116,93 @@ python run.py --step submit # 仅浏览器填报 python run.py -u 工号 -p 密码 ``` +### 5. 填写易耗品出库单(CLI) + +需已生成 `invoice_summary.csv`,且本机已安装 **Microsoft Word**: + +```bash +python -m app.fill_consumable_doc +python -m app.fill_consumable_doc --csv invoice_summary.csv --doc "易耗品、出库单.doc" +python -m app.fill_consumable_doc --no-backup # 不生成 .doc.bak 备份 +``` + +填写规则概要: + +- 从 `规格型号` 解析品名、规格、单位、数量、单价;`价税合计` 写入金额列 +- 单价/金额保留两位小数;表格内统一为 **宋体五号(10.5 磅)** +- 存放地点取自 `consumable_storage`;购货人/领用人签字、备注保持空白 + ## 执行步骤说明 | 步骤 | 命令 | 说明 | |------|------|------| -| 发票提取 | `--step invoice` | 扫描根目录 PDF,提取发票号码、金额、销售方等信息,生成 `invoice_summary.csv` 和 `.md` | -| OCR 识别 | `--step ocr` | 对支付截图执行 OCR,识别刷卡日期、刷卡金额、持卡人姓名,回填到 CSV | -| 浏览器填报 | `--step submit` | 打开浏览器,登录信息门户 → 进入报销系统 → 自动填单、录入明细、上传附件 | +| 发票提取 | `--step invoice` | 扫描根目录 PDF,生成 `invoice_summary.csv` / `.md` | +| OCR 识别 | `--step ocr` | 识别支付截图,回填刷卡日期、金额、持卡人等到 CSV | +| 浏览器填报 | `--step submit` | 登录信息门户 → 报销系统 → 自动填单、上传附件 | -> 分步执行时,上一步的 CSV 产物会自动成为下一步的输入。 +> 分步执行时,上一步的 CSV 会自动成为下一步的输入。 + +### CSV 字段说明 + +| 列名 | 说明 | +|------|------| +| 序号 | 行号 | +| 发票号码 | 电子发票号码 | +| 开票日期 | 开票日期 | +| 项目名称 / 规格型号 | 货物或应税劳务信息 | +| 价税合计 | 发票含税金额 | +| 销售方名称 | 销方名称 | +| 人员姓名 / 刷卡日期 / 公务卡号 / 刷卡金额 | OCR 自支付截图回填 | +| 备注 / 工号 | 可手工或 Web 端编辑补充 | ## Web 服务 -提供浏览器界面,上传文件即可自动处理: +提供浏览器界面:上传文件 → 自动处理 → 在线编辑 → 下载产物 → 可选提交财务系统。 ```bash python web/app.py ``` -访问 `http://localhost:5000`,上传文件并填写配置后点击「开始处理」。 +访问 `http://localhost:5000`。 -### 两种处理模式 +### 推荐使用流程 + +1. 上传 PDF + 支付截图(或上传已有 CSV) +2. 填写配置(账号、密码、姓名、公务卡号、存放地点等),可上传 `config.json` 一键填充 +3. 点击 **开始处理** — 完成发票提取、OCR、生成 CSV,并自动填写 **易耗品、出库单.doc** +4. 在 **下载文件** 区域下载 CSV / Markdown / 出库单 Word +5. 在表格中核对、修改发票数据(提交财务系统前会自动保存) +6. 确认无误后点击 **提交到财务系统** + +### 处理模式 | 模式 | 入口 | 说明 | |------|------|------| -| **PDF 模式** | 上传 PDF + 截图 | 自动提取发票信息 → OCR 识别刷卡记录 → 生成 CSV → 可选浏览器填报 | -| **CSV 快捷模式** | 上传已有 CSV 文件 | 跳过提取和 OCR,直接使用 CSV 数据进行浏览器填报 | +| **PDF 模式** | 上传 PDF + 截图 | 提取发票 → OCR → 生成 CSV + 出库单 | +| **CSV 快捷模式** | 仅上传 CSV | 跳过提取与 OCR,直接生成出库单并进入编辑/提交 | -### 功能说明 +### 功能一览 | 功能 | 说明 | |------|------| -| 发票提取 + OCR | 上传 PDF 后自动完成,无需手动操作 | -| CSV 快捷上传 | 已有发票数据 CSV 可直接上传,跳过前面的步骤 | -| 浏览器填报 | 勾选「同时提交到财务系统」后自动运行 | -| 实时日志 | 处理进度通过 SSE 实时推送 | -| 下载 CSV | 处理后下载发票汇总表 | -| 配置上传 | 可上传 `config.json` 自动填充表单 | -| 手机扫码上传 | 支付截图区域显示二维码,手机端扫码后可拍照/选图上传,PC 端实时同步接收 | +| 发票提取 + OCR | 上传 PDF 后自动完成 | +| 易耗品出库单 | 处理完成后自动生成 Word,可下载 | +| 表格在线编辑 | 处理完成后可修改 CSV 各字段;保存后重新生成出库单 | +| 财务系统填报 | 单独按钮触发,处理阶段不会自动提交 | +| 实时日志 | SSE 推送处理进度 | +| 配置上传 | 支持上传 `config.json` 填充表单 | +| 手机扫码上传 | 二维码打开移动端页面,拍照上传支付截图,PC 端轮询同步 | -> Web 模式下浏览器以无头模式运行,不会弹出窗口。 -> 若未上传 PDF 附件,浏览器填报阶段将自动跳过附件上传步骤。 +> Web 端浏览器填报以无头模式运行。未上传 PDF 时,填报阶段会跳过附件上传。 +> 出库单生成需要 **Windows + Word + pywin32**;若失败,页面会显示具体原因,CSV 等其它产物仍可正常使用。 + +接口说明见 [API.md](./API.md)。 ## 注意事项 -- 第三步会打开浏览器窗口,请勿关闭或切换标签页 -- 首次运行可能需要手动处理 SSO 登录(如已保存会话则跳过) -- 调试截图保存在 `images/` 目录,出错时可查看 -- `invoice_summary.csv` 中空白的字段会在 OCR 步骤自动回填,不会覆盖已有数据 -- 提交按钮默认未启用,确认数据无误后可在 `app/bot.py` 中取消注释 `bot.submit()` \ No newline at end of file +- 浏览器填报时会打开或使用 Chromium,请勿手动干扰自动化流程 +- 首次运行可能需要处理 SSO 登录(已保存会话时可跳过) +- 调试截图保存在 `images/` 目录 +- OCR 不会覆盖 CSV 中已有非空字段 +- 项目根目录需保留 `易耗品、出库单.doc` 模板;Web 每次从模板复制到会话目录再填写,不修改原模板 +- `config.json` 含敏感信息,请勿提交到公开仓库 diff --git a/app/bot.py b/app/bot.py index e71a861..4af1b12 100644 --- a/app/bot.py +++ b/app/bot.py @@ -297,23 +297,13 @@ class ReimburseBot: for i, inv in enumerate(invoices): file_path = attachment_files[i] if i < len(attachment_files) else None - - self.page.click("#insertAcc", timeout=5000) - self.page.wait_for_timeout(1000) - try: + self._wait_for("#insertAcc", timeout=20000) # 等待增加按钮出现 + self.page.click("#insertAcc", timeout=5000) #点击增加按钮出现 self._wait_for("#fjlx", timeout=5000) - except Exception: - pass - - try: self.page.select_option("#fjlx", "1") - except Exception: - pass - - try: explanation = f"{inv['item_name']} - {inv['invoice_no']}" - self.page.fill("#fpsmxx", explanation) + self.page.fill("#fpsmxx", explanation) except Exception: pass @@ -323,16 +313,14 @@ class ReimburseBot: self.page.wait_for_timeout(1000) except Exception as e: log.error(f"文件上传失败: {e}") - try: self.page.click("#cjtj", timeout=5000) - self.page.wait_for_timeout(1500) except Exception: try: self.page.press("body", "Escape") except Exception: pass - + log.info("上传附件完成") except Exception as e: log.error(f"附件上传失败: {e}") self._screenshot("step6_error") diff --git a/app/config.py b/app/config.py index a24f0ad..77f5016 100644 --- a/app/config.py +++ b/app/config.py @@ -29,5 +29,6 @@ def load_config() -> dict: "default_name": raw.get("default_name", ""), "default_card_no": raw.get("default_card_no", ""), "default_person_id": raw.get("default_person_id", ""), + "consumable_storage": raw.get("consumable_storage", "躬行楼 C205"), "attachment_dir": project_root / "attachments", } \ No newline at end of file diff --git a/app/fill_consumable_doc.py b/app/fill_consumable_doc.py new file mode 100644 index 0000000..38c2a0b --- /dev/null +++ b/app/fill_consumable_doc.py @@ -0,0 +1,243 @@ +""" +将 invoice_summary.csv 填入「易耗品、出库单.doc」表格。 + +仅写入表格数据单元格,保留原模板字体、边框与版式。 +""" + +from __future__ import annotations + +import argparse +import re +import shutil +from pathlib import Path + +from . import get_logger +from .bot import load_invoice_data +from .config import load_config + +log = get_logger("fill_consumable_doc") + +CONSUMABLE_DOC_FILENAME = "易耗品、出库单.doc" + +# Word COM 常量 +WD_CHARACTER = 1 + +# 表格统一字体:宋体、五号(10.5 磅) +TABLE_FONT_NAME = "宋体" +TABLE_FONT_SIZE = 10.5 + + +def _split_name_spec(left: str) -> tuple[str, str]: + m = re.search(r"(\S+一批)\s*$", left) + if m: + return m.group(1), left[: m.start()].strip() + parts = left.split(" ", 1) + if len(parts) == 2: + return parts[0], parts[1] + return left, "" + + +def parse_spec_model(spec: str) -> dict[str, str]: + spec = (spec or "").strip() + if " 个 " not in spec: + return { + "product_name": spec, + "spec": "", + "unit": "", + "qty": "", + "unit_price": "", + } + + left, right = spec.split(" 个 ", 1) + product_name, model_spec = _split_name_spec(left.strip()) + tokens = right.split() + + qty = "" + unit_price = "" + if len(tokens) >= 4 and re.fullmatch(r"\d+(?:\.\d+)?", tokens[0]): + qty, unit_price = tokens[0], tokens[1] + elif tokens and re.fullmatch(r"\d+(?:\.\d+)?", tokens[0]): + qty, unit_price = "1", tokens[0] + + return { + "product_name": product_name, + "spec": model_spec, + "unit": "个", + "qty": qty, + "unit_price": unit_price, + } + + +def _format_money(value: str | float) -> str: + """单价、金额:固定保留两位小数。""" + if value is None or value == "": + return "" + try: + num = float(value) + except (TypeError, ValueError): + return str(value) + return f"{num:.2f}" + + +def _format_cn_date(date_str: str) -> str: + if not date_str: + return "" + parts = date_str.replace("-", "/").split("/") + if len(parts) != 3: + return date_str + y, m, d = parts[0], str(int(parts[1])), str(int(parts[2])) + return f"{y}年{m}月{d}日" + + +def _apply_font(rng) -> None: + """将范围字体设为宋体五号(含数字与英文)。""" + font = rng.Font + font.Name = TABLE_FONT_NAME + font.NameFarEast = TABLE_FONT_NAME + font.NameAscii = TABLE_FONT_NAME + font.NameOther = TABLE_FONT_NAME + font.NameBi = TABLE_FONT_NAME + font.Size = TABLE_FONT_SIZE + + +def _set_cell_value(cell, text: str) -> None: + """写入单元格正文(不含末尾单元格标记)。""" + rng = cell.Range + rng.MoveEnd(WD_CHARACTER, -1) + rng.Text = "" if text is None else str(text) + _apply_font(rng) + + +def _normalize_table_font(tbl) -> None: + """填写完成后统一整张表的字体。""" + for row in tbl.Rows: + for cell in row.Cells: + rng = cell.Range + rng.MoveEnd(WD_CHARACTER, -1) + _apply_font(rng) + + +def _replace_date_in_doc(doc, new_date: str) -> None: + """仅替换表头段落中的日期文字,不改动段落其余部分。""" + if not new_date: + return + try: + para = doc.Paragraphs(3) + except Exception: + return + rng = para.Range + text = rng.Text.replace("\r", "").replace("\x07", "") + m = re.search(r"\d{4}年\d{1,2}月\d{1,2}日", text) + if not m: + return + start = rng.Start + m.start() + end = rng.Start + m.end() + doc.Range(Start=start, End=end).Text = new_date + + +def fill_consumable_doc( + csv_path: str | Path, + doc_path: str | Path, + config: dict | None = None, + backup: bool = True, +) -> Path: + csv_path = Path(csv_path) + doc_path = Path(doc_path) + if config is None: + config = load_config() + invoices = load_invoice_data(str(csv_path), config) + + if backup: + bak = doc_path.with_suffix(doc_path.suffix + ".bak") + shutil.copy2(doc_path, bak) + + import win32com.client + + word = win32com.client.Dispatch("Word.Application") + word.Visible = False + word.DisplayAlerts = 0 + doc = word.Documents.Open(str(doc_path.resolve())) + + try: + if invoices: + cn_date = _format_cn_date(invoices[0].get("invoice_date", "")) + _replace_date_in_doc(doc, cn_date) + + tbl = doc.Tables(1) + storage = config.get("consumable_storage", "躬行楼 C205") + + for i, inv in enumerate(invoices): + row_idx = i + 2 + if row_idx > tbl.Rows.Count: + break + + parsed = parse_spec_model(inv.get("spec_model", "")) + amount = _format_money(inv.get("total_amount", "")) + unit_price = _format_money(parsed["unit_price"]) + qty = parsed["qty"] + if qty and qty.isdigit(): + qty = str(int(qty)) + + values = [ + str(inv.get("seq", i + 1)), + parsed["product_name"], + parsed["spec"], + parsed["unit"], + qty, + unit_price, + amount, + "", # 购货人签字 — 保持空白 + storage, + "", # 领用人签字 — 保持空白 + "", # 备注 — 保持空白,避免撑破版式 + ] + + for col_idx, val in enumerate(values, start=1): + _set_cell_value(tbl.Cell(row_idx, col_idx), val) + + _normalize_table_font(tbl) + + doc.Save() + finally: + doc.Close() + word.Quit() + + return doc_path + + +def fill_consumable_from_template( + csv_path: str | Path, + template_path: str | Path, + output_path: str | Path, + config: dict | None = None, +) -> Path: + """从模板复制并填写出库单(Web 会话每次从模板重新生成)。""" + template_path = Path(template_path) + output_path = Path(output_path) + if not template_path.exists(): + raise FileNotFoundError(f"出库单模板不存在: {template_path}") + shutil.copy2(template_path, output_path) + return fill_consumable_doc(csv_path, output_path, config=config, backup=False) + + +def main() -> None: + root = Path(__file__).resolve().parents[1] + parser = argparse.ArgumentParser(description="将发票 CSV 填入易耗品出库单") + parser.add_argument("--csv", default=str(root / "invoice_summary.csv")) + parser.add_argument("--doc", default=str(root / "易耗品、出库单.doc")) + parser.add_argument("--config", default=str(root / "config.json")) + parser.add_argument("--no-backup", action="store_true") + args = parser.parse_args() + + cfg = None + if Path(args.config).exists(): + import json + + with open(args.config, encoding="utf-8") as f: + cfg = {**load_config(), **json.load(f)} + out = fill_consumable_doc(args.csv, args.doc, config=cfg, backup=not args.no_backup) + print(f"已填写并保存: {out}") + + +if __name__ == "__main__": + main() diff --git a/config.example.json b/config.example.json new file mode 100644 index 0000000..b33d40b --- /dev/null +++ b/config.example.json @@ -0,0 +1,12 @@ +{ + "username": "你的工号", + "password": "你的密码", + "sso_login_url": "https://tyrz.fynu.edu.cn/sso/login", + "portal_url": "https://tyrz.fynu.edu.cn/oshall", + "reimburse_url": "http://210.45.32.214:8081", + "reimburse_page": "/expen/common/common?v=4.0", + "default_name": "默认报销人姓名", + "default_card_no": "默认公务卡号", + "default_person_id": "默认人员编号", + "consumable_storage": "躬行楼 C205" +} diff --git a/web/app.py b/web/app.py index eedaec2..39c447a 100644 --- a/web/app.py +++ b/web/app.py @@ -16,6 +16,7 @@ import threading import time import uuid from pathlib import Path +from urllib.parse import quote from flask import Flask, Response, jsonify, render_template, request, stream_with_context @@ -25,8 +26,16 @@ sys.path.insert(0, str(PROJECT_ROOT)) from app.config import load_config as load_project_config from app.extractor import extract_invoices, save_csv, save_markdown +from app.fill_consumable_doc import ( + CONSUMABLE_DOC_FILENAME, + fill_consumable_from_template, +) +from app import get_logger from app.ocr import enrich_with_ocr, _save_csv as save_ocr_csv, save_markdown_from_csv, _load_csv as load_ocr_csv +fill_log = get_logger("fill_consumable_doc") +CONSUMABLE_TEMPLATE = PROJECT_ROOT / CONSUMABLE_DOC_FILENAME + app = Flask(__name__, template_folder="templates") UPLOAD_BASE = PROJECT_ROOT / "web" / "uploads" @@ -73,7 +82,7 @@ def _install_log_collector(session_dir: Path) -> _SSELogHandler: handler.setFormatter(fmt) handler.setLevel(logging.INFO) - for name in ["extractor", "ocr", "pipeline", "bot"]: + for name in ["extractor", "ocr", "pipeline", "bot", "fill_consumable_doc"]: logger = logging.getLogger(name) logger.setLevel(logging.INFO) logger.addHandler(handler) @@ -82,21 +91,79 @@ def _install_log_collector(session_dir: Path) -> _SSELogHandler: def _remove_log_collector(handler: _SSELogHandler): - for name in ["extractor", "ocr", "pipeline", "bot"]: + for name in ["extractor", "ocr", "pipeline", "bot", "fill_consumable_doc"]: logging.getLogger(name).removeHandler(handler) handler.close_file() # ================================================================ -# 管道入口 +# 出库单填写 # ================================================================ + +def _load_session_config(session_dir: Path) -> dict: + config = load_project_config() + cfg_path = session_dir / "config.json" + if cfg_path.exists(): + with open(cfg_path, encoding="utf-8") as f: + config.update(json.load(f)) + return config + + +def _resolve_invoice_csv(session_dir: Path) -> Path | None: + csv_path = session_dir / "invoice_summary.csv" + if csv_path.exists(): + return csv_path + for f in session_dir.glob("*.csv"): + return f + return None + + +def _try_fill_consumable_doc(session_dir: Path, config: dict) -> dict: + """根据 CSV 填写易耗品出库单,供会话目录下载。""" + if not CONSUMABLE_TEMPLATE.exists(): + fill_log.warning("出库单模板不存在: %s", CONSUMABLE_TEMPLATE) + return {"ok": False, "error": "出库单模板不存在,请将模板放在项目根目录"} + + csv_path = _resolve_invoice_csv(session_dir) + if csv_path is None: + return {"ok": False, "error": "未找到发票 CSV"} + + out_doc = session_dir / CONSUMABLE_DOC_FILENAME + try: + fill_log.info("开始填写出库单: %s", out_doc.name) + fill_consumable_from_template( + csv_path, CONSUMABLE_TEMPLATE, out_doc, config=config + ) + fill_log.info("出库单填写完成") + return {"ok": True, "doc_filename": CONSUMABLE_DOC_FILENAME} + except ImportError: + fill_log.error("填写出库单需要 pywin32,请执行: pip install pywin32") + return {"ok": False, "error": "服务器未安装 pywin32,无法生成 Word 出库单"} + except Exception as e: + fill_log.exception("填写出库单失败: %s", e) + return {"ok": False, "error": str(e)} + + +def _append_doc_download(result: dict, session_id: str, doc_fill: dict) -> None: + if doc_fill.get("ok"): + fn = doc_fill["doc_filename"] + result["doc_url"] = f"/api/download/{session_id}/{quote(fn)}" + result["doc_ok"] = True + else: + result["doc_ok"] = False + result["doc_error"] = doc_fill.get("error", "未知错误") + + # ================================================================ # 管道入口 # ================================================================ -def run_pipeline_web(session_dir: Path, config: dict, run_bot: bool = False): - """在 Web 会话目录中执行管道,结果写入 session 目录下的文件""" +def run_pipeline_web(session_dir: Path, config: dict): + """在 Web 会话目录中执行提取+OCR,结果写入 session 目录下的文件 + + 注意:不再自动提交财务系统。提交通由 /api/submit-financial/ 触发。 + """ start = time.time() # ---- Step 1: 发票提取 ---- @@ -117,25 +184,21 @@ def run_pipeline_web(session_dir: Path, config: dict, run_bot: bool = False): save_ocr_csv(csv_path, rows) save_markdown_from_csv(csv_path, rows) - # ---- Step 3: 浏览器填报(可选)---- - if run_bot: - from app.bot import load_invoice_data, run_bot_web - - bot_invoices = load_invoice_data(str(csv_path), config) - run_bot_web(config, bot_invoices, session_dir) - elapsed = time.time() - start - return { + result = { "ok": True, "elapsed": f"{elapsed:.1f}s", "invoice_count": len(rows), "csv_url": f"/api/download/{session_dir.name}/invoice_summary.csv", "md_url": f"/api/download/{session_dir.name}/invoice_summary.md", } + doc_fill = _try_fill_consumable_doc(session_dir, config) + _append_doc_download(result, session_dir.name, doc_fill) + return result -def run_csv_pipeline_web(session_dir: Path, config: dict, csv_filename: str, run_bot: bool = False): - """直接使用上传的 CSV 文件进行填报,跳过 PDF 提取和 OCR""" +def run_csv_pipeline_web(session_dir: Path, config: dict, csv_filename: str): + """直接使用上传的 CSV 文件,跳过 PDF 提取和 OCR""" start = time.time() csv_path = session_dir / csv_filename @@ -147,20 +210,29 @@ def run_csv_pipeline_web(session_dir: Path, config: dict, csv_filename: str, run if rows is None: return {"ok": False, "error": "CSV 读取失败"} - # 浏览器填报 - if run_bot: - from app.bot import load_invoice_data, run_bot_web - - bot_invoices = load_invoice_data(str(csv_path), config) - run_bot_web(config, bot_invoices, session_dir) - elapsed = time.time() - start - return { + result = { "ok": True, "elapsed": f"{elapsed:.1f}s", "invoice_count": len(rows), "csv_url": f"/api/download/{session_dir.name}/{csv_filename}", } + doc_fill = _try_fill_consumable_doc(session_dir, config) + _append_doc_download(result, session_dir.name, doc_fill) + return result + + +def run_financial_submit(session_dir: Path, config: dict) -> dict: + """执行财务系统填报(从前端确认后调用)""" + csv_path = session_dir / "invoice_summary.csv" + if not csv_path.exists(): + return {"ok": False, "error": "未找到发票数据,请先处理"} + + from app.bot import load_invoice_data, run_bot_web + + bot_invoices = load_invoice_data(str(csv_path), config) + run_bot_web(config, bot_invoices, session_dir) + return {"ok": True} # ================================================================ @@ -230,13 +302,12 @@ def list_files(session_id: str): @app.route("/api/process/", methods=["POST"]) def start_process(session_id: str): - """启动管道处理""" + """启动管道处理(仅提取+OCR,不自动提交财务系统)""" session_dir = _validate_session(session_id) if isinstance(session_dir, tuple): return session_dir body = request.get_json(silent=True) or {} - run_bot_flag = body.get("submit", False) mode = body.get("mode", "auto") # "pdf", "csv", or "auto" # 读取配置 @@ -253,27 +324,24 @@ def start_process(session_id: str): result = {"ok": False, "error": "未知错误"} try: if mode == "csv": - # CSV 模式:直接使用上传的 CSV,跳过 PDF 提取和 OCR csv_files = list(session_dir.glob("*.csv")) if not csv_files: result = {"ok": False, "error": "未找到 CSV 文件"} else: - result = run_csv_pipeline_web(session_dir, config, csv_files[0].name, run_bot_flag) + result = run_csv_pipeline_web(session_dir, config, csv_files[0].name) else: - # 自动检测:如果有 CSV 则走 csv 管道,否则走 pdf 管道 csv_files = list(session_dir.glob("*.csv")) pdf_files = list(session_dir.glob("*.pdf")) if csv_files and not pdf_files: - result = run_csv_pipeline_web(session_dir, config, csv_files[0].name, run_bot_flag) + result = run_csv_pipeline_web(session_dir, config, csv_files[0].name) else: - result = run_pipeline_web(session_dir, config, run_bot_flag) + result = run_pipeline_web(session_dir, config) except BaseException as e: result = {"ok": False, "error": str(e)} if isinstance(e, (KeyboardInterrupt, SystemExit)): raise finally: try: - # 原子写入:先写临时文件,再重命名,避免 SSE 读到截断的空文件 tmp_path = session_dir / (SESSION_RESULT_FILE + ".tmp") with open(tmp_path, "w", encoding="utf-8") as f: json.dump(result, f, ensure_ascii=False) @@ -337,11 +405,156 @@ def download_file(session_id: str, filename: str): if isinstance(session_dir, tuple): return session_dir - filepath = session_dir / filename + # 防止路径穿越 + safe_name = Path(filename).name + filepath = session_dir / safe_name if not filepath.exists(): return jsonify({"error": "文件不存在"}), 404 - return Response(filepath.read_bytes(), mimetype="application/octet-stream") + if safe_name.endswith(".doc"): + mimetype = "application/msword" + elif safe_name.endswith(".csv"): + mimetype = "text/csv; charset=utf-8" + elif safe_name.endswith(".md"): + mimetype = "text/markdown; charset=utf-8" + else: + mimetype = "application/octet-stream" + + disposition = f"attachment; filename*=UTF-8''{quote(safe_name)}" + return Response( + filepath.read_bytes(), + mimetype=mimetype, + headers={"Content-Disposition": disposition}, + ) + + +@app.route("/api/data/", methods=["GET"]) +def get_invoice_data(session_id: str): + """读取发票数据并返回 JSON(供前端表格编辑)""" + session_dir = _validate_session(session_id) + if isinstance(session_dir, tuple): + return session_dir + + csv_path = session_dir / "invoice_summary.csv" + if not csv_path.exists(): + # CSV 模式下可能是其他文件名 + csv_files = list(session_dir.glob("*.csv")) + csv_files = [f for f in csv_files if f.name != SESSION_RESULT_FILE] + if csv_files: + csv_path = csv_files[0] + else: + return jsonify({"error": "未找到发票数据,请先处理"}), 404 + + rows = load_ocr_csv(csv_path) + if rows is None: + return jsonify({"error": "CSV 读取失败"}), 500 + + # 添加行号用于编辑追踪 + data = [] + for i, row in enumerate(rows): + entry = dict(row) + entry["__row"] = i + data.append(entry) + + # 返回原始字段顺序(去掉内部字段) + fields = [k for k in rows[0].keys() if not k.startswith('__')] if rows else [] + + return jsonify({"csv_filename": csv_path.name, "fields": fields, "data": data}) + + +@app.route("/api/save/", methods=["POST"]) +def save_invoice_data(session_id: str): + """保存前端编辑后的发票数据到 CSV""" + session_dir = _validate_session(session_id) + if isinstance(session_dir, tuple): + return session_dir + + body = request.get_json(silent=True) or {} + data = body.get("data", []) + csv_filename = body.get("csv_filename", "invoice_summary.csv") + + csv_path = session_dir / csv_filename + if not csv_path.exists(): + return jsonify({"error": "CSV 文件不存在"}), 404 + + # 读取原 CSV 获取字段顺序(使用第一个数据的 keys) + original_rows = load_ocr_csv(csv_path) + if original_rows is None or len(original_rows) == 0: + return jsonify({"error": "无法读取原始 CSV 结构"}), 500 + + # 从原数据中获取字段顺序(去掉内部字段) + fieldnames = list(original_rows[0].keys()) + + import csv as csv_module + + with open(csv_path, "w", newline="", encoding="utf-8-sig") as f: + writer = csv_module.DictWriter(f, fieldnames=fieldnames) + writer.writeheader() + for entry in data: + row = {k: entry.get(k, "") for k in fieldnames} + writer.writerow(row) + + resp = {"ok": True} + config = _load_session_config(session_dir) + doc_fill = _try_fill_consumable_doc(session_dir, config) + if doc_fill.get("ok"): + fn = doc_fill["doc_filename"] + resp["doc_url"] = f"/api/download/{session_id}/{quote(fn)}" + resp["doc_ok"] = True + else: + resp["doc_ok"] = False + resp["doc_error"] = doc_fill.get("error") + return jsonify(resp) + + +@app.route("/api/submit-financial/", methods=["POST"]) +def submit_financial(session_id: str): + """手动触发财务系统填报""" + session_dir = _validate_session(session_id) + if isinstance(session_dir, tuple): + return session_dir + + # 读取配置 + config_path = session_dir / "config.json" + if not config_path.exists(): + return jsonify({"error": "未找到配置,请先配置后处理"}), 400 + + with open(config_path, encoding="utf-8") as f: + config = json.load(f) + + # 清除上次处理留下的结果文件,避免 SSE 误判为已完成 + result_file = session_dir / SESSION_RESULT_FILE + if result_file.exists(): + result_file.unlink() + + # 在后台线程执行提交 + handler = _install_log_collector(session_dir) + + def _run(): + result = {"ok": False, "error": "未知错误"} + try: + submit_result = run_financial_submit(session_dir, config) + if submit_result.get("ok"): + result = {"ok": True} + else: + result = submit_result + except BaseException as e: + result = {"ok": False, "error": str(e)} + if isinstance(e, (KeyboardInterrupt, SystemExit)): + raise + finally: + try: + tmp_path = session_dir / (SESSION_RESULT_FILE + ".tmp") + with open(tmp_path, "w", encoding="utf-8") as f: + json.dump({"ok": True, "submit_ok": result.get("ok"), "submit_error": result.get("error")}, f, ensure_ascii=False) + tmp_path.replace(session_dir / SESSION_RESULT_FILE) + except Exception: + pass + _remove_log_collector(handler) + + threading.Thread(target=_run, daemon=True).start() + + return jsonify({"status": "started"}) # ================================================================ @@ -358,7 +571,14 @@ def _validate_session(session_id: str): def _build_web_config(body: dict) -> dict: """从请求体构建配置""" config = load_project_config() - for key in ("username", "password", "default_name", "default_card_no", "default_person_id"): + for key in ( + "username", + "password", + "default_name", + "default_card_no", + "default_person_id", + "consumable_storage", + ): if body.get(key): config[key] = body[key] return config diff --git a/web/static/css/index.css b/web/static/css/index.css new file mode 100644 index 0000000..d67f19c --- /dev/null +++ b/web/static/css/index.css @@ -0,0 +1,24 @@ +body { background: #f5f7fa; } +.header { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: #fff; padding: 24px 0 20px; } +.upload-zone { + border: 2px dashed #ccc; border-radius: 12px; padding: 28px; text-align: center; + cursor: pointer; transition: all .2s; background: #fff; min-height: 100px; +} +.upload-zone:hover, .upload-zone.dragover { border-color: #667eea; background: #f0f2ff; } +.upload-zone.active { border-color: #28a745; background: #f0fff4; } +.upload-zone .icon { font-size: 32px; color: #aaa; margin-bottom: 8px; } +.file-tag { display: inline-block; background: #e8f0fe; border-radius: 4px; padding: 2px 10px; margin: 3px; font-size: 13px; } +.file-tag .remove { cursor: pointer; color: #c00; margin-left: 6px; font-weight: bold; } +.log-container { background: #1e1e1e; color: #d4d4d4; border-radius: 8px; padding: 14px; height: 360px; overflow-y: auto; font-family: Consolas, monospace; font-size: 13px; line-height: 1.6; white-space: pre-wrap; word-break: break-all; } +.log-container .empty { color: #666; font-style: italic; } +.section-title { font-size: 15px; font-weight: 600; color: #333; margin-bottom: 12px; } +.btn-process { font-size: 17px; padding: 10px 40px; } +.status-badge { font-size: 13px; } + +/* 可编辑表格 */ +.table-editable { font-size: 13px; } +.table-editable th { position: sticky; top: 0; background: #f8f9fa; z-index: 1; font-weight: 600; white-space: nowrap; } +.table-editable td { vertical-align: middle; } +.table-editable input.form-control { font-size: 13px; padding: 4px 8px; min-width: 80px; } +.table-wrapper { max-height: 500px; overflow-y: auto; border: 1px solid #dee2e6; border-radius: 8px; } +.edit-note { font-size: 12px; color: #888; margin-bottom: 8px; } \ No newline at end of file diff --git a/web/static/js/index.js b/web/static/js/index.js new file mode 100644 index 0000000..cf338e8 --- /dev/null +++ b/web/static/js/index.js @@ -0,0 +1,517 @@ +let sessionId = null; +const pdfFiles = [], imgFiles = []; +let csvFile = null; +let invoiceData = []; // 当前编辑数据 [{__row, ...fields}] +let csvFilename = ''; // 当前 CSV 文件名 +let lastDownloadUrls = {}; // 最近一次可下载文件链接 + +// ---- Session ---- +async function ensureSession() { + if (sessionId) return sessionId; + const r = await fetch('/api/session', { method: 'POST' }); + const d = await r.json(); + sessionId = d.session_id; + return sessionId; +} + +// ---- 上传 ---- +function handleFiles(input, type) { + const files = Array.from(input.files); + const list = type === 'pdf' ? pdfFiles : imgFiles; + const listId = type === 'pdf' ? 'pdf-list' : 'img-list'; + const zoneId = type === 'pdf' ? 'pdf-zone' : 'img-zone'; + + files.forEach(f => { + if (!list.find(x => x.name === f.name)) { + f.__source = 'local'; // 标记为本地手动选择 + list.push(f); + } + }); + + renderFileList(type); + document.getElementById(zoneId).classList.add('active'); + input.value = ''; +} + +function removeFile(type, index) { + const list = type === 'pdf' ? pdfFiles : imgFiles; + list.splice(index, 1); + renderFileList(type); + if (list.length === 0) { + document.getElementById(type === 'pdf' ? 'pdf-zone' : 'img-zone').classList.remove('active'); + } +} + +function renderFileList(type) { + const list = type === 'pdf' ? pdfFiles : imgFiles; + const box = document.getElementById(type === 'pdf' ? 'pdf-list' : 'img-list'); + box.innerHTML = list.map((f, i) => + `${f.name}×` + ).join(''); +} + +// ---- CSV 上传 ---- +function handleCsvFile(input) { + const file = input.files[0]; + if (!file) return; + csvFile = file; + document.getElementById('csv-zone').classList.add('active'); + document.getElementById('csv-list').innerHTML = + `${file.name}×`; + input.value = ''; +} + +function removeCsvFile() { + csvFile = null; + document.getElementById('csv-zone').classList.remove('active'); + document.getElementById('csv-list').innerHTML = ''; +} + +// ---- 配置上传 ---- +function handleConfigUpload(input) { + const file = input.files[0]; + if (!file) return; + const reader = new FileReader(); + reader.onload = function(e) { + try { + const cfg = JSON.parse(e.target.result); + const map = { + 'cfg-username': cfg.username, + 'cfg-password': cfg.password, + 'cfg-name': cfg.default_name, + 'cfg-card': cfg.default_card_no, + 'cfg-person-id': cfg.default_person_id, + 'cfg-storage': cfg.consumable_storage, + }; + for (const [id, val] of Object.entries(map)) { + if (val) document.getElementById(id).value = val; + } + // 同步 config.json 中的工号和公务卡号到表格 + if (cfg.username) syncConfigToTable('工号'); + if (cfg.default_card_no) syncConfigToTable('公务卡号'); + alert('配置已加载'); + } catch (err) { + alert('config.json 解析失败: ' + err.message); + } + }; + reader.readAsText(file); + input.value = ''; +} + +// ---- 拖拽 ---- +['pdf','img'].forEach(type => { + const zone = document.getElementById(type + '-zone'); + zone.addEventListener('dragover', e => { e.preventDefault(); zone.classList.add('dragover'); }); + zone.addEventListener('dragleave', () => zone.classList.remove('dragover')); + zone.addEventListener('drop', e => { + e.preventDefault(); + zone.classList.remove('dragover'); + const files = Array.from(e.dataTransfer.files).filter(f => { + if (type === 'pdf') return f.name.toLowerCase().endsWith('.pdf'); + /\.(png|jpe?g|bmp|webp)$/i.test(f.name); + }); + if (files.length) { + const list = type === 'pdf' ? pdfFiles : imgFiles; + files.forEach(f => { + f.__source = 'local'; // 标记为本地拖拽 + if (!list.find(x => x.name === f.name)) list.push(f); + }); + renderFileList(type); + zone.classList.add('active'); + } + }); +}); + +// CSV 拖拽 +const csvZone = document.getElementById('csv-zone'); +csvZone.addEventListener('dragover', e => { e.preventDefault(); csvZone.classList.add('dragover'); }); +csvZone.addEventListener('dragleave', () => csvZone.classList.remove('dragover')); +csvZone.addEventListener('drop', e => { + e.preventDefault(); + csvZone.classList.remove('dragover'); + const file = Array.from(e.dataTransfer.files).find(f => f.name.toLowerCase().endsWith('.csv')); + if (file) handleCsvFile({ files: [file] }); +}); + +// ---- 处理 ---- +async function startProcess() { + const isCsvMode = !!csvFile; + if (!isCsvMode && !pdfFiles.length && !imgFiles.length) { + alert('请先上传文件或 CSV'); + return; + } + + const btn = document.getElementById('btn-start'); + btn.disabled = true; + btn.textContent = '处理中...'; + document.getElementById('status').innerHTML = '上传中...'; + document.getElementById('log-box').innerHTML = ''; + document.getElementById('edit-section').style.display = 'none'; + document.getElementById('download-section').style.display = 'none'; + + try { + await ensureSession(); + + if (isCsvMode) { + const fd = new FormData(); + fd.append('file', csvFile); + await fetch(`/api/upload-csv/${sessionId}`, { method: 'POST', body: fd }); + } else { + const allFiles = [...pdfFiles.map(f => ({f, t:'pdf'})), ...imgFiles.map(f => ({f, t:'img'}))]; + for (const {f} of allFiles) { + const fd = new FormData(); + fd.append('file', f); + await fetch(`/api/upload/${sessionId}`, { method: 'POST', body: fd }); + } + } + + document.getElementById('status').innerHTML = '处理中...'; + + const cfg = { + username: document.getElementById('cfg-username').value, + password: document.getElementById('cfg-password').value, + default_name: document.getElementById('cfg-name').value, + default_card_no: document.getElementById('cfg-card').value, + default_person_id: document.getElementById('cfg-person-id').value, + consumable_storage: document.getElementById('cfg-storage').value, + mode: isCsvMode ? 'csv' : 'auto', + }; + + await fetch(`/api/process/${sessionId}`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(cfg), + }); + + // 监听 SSE 日志 + const es = new EventSource(`/api/logs/${sessionId}`); + const logBox = document.getElementById('log-box'); + let firstLine = true; + + es.addEventListener('message', e => { + if (firstLine) { logBox.innerHTML = ''; firstLine = false; } + try { + const msg = JSON.parse(e.data); + if (msg.type === 'done') { + es.close(); + const result = msg.result; + document.getElementById('status').innerHTML = result.ok + ? '完成' + : '失败'; + btn.disabled = false; + btn.textContent = '开始处理'; + + if (result.ok) { + showDownloadLinks(result); + loadInvoiceData(); // 加载可编辑数据 + } else { + alert('处理失败: ' + (result.error || '未知错误')); + } + return; + } + } catch (err) {} + logBox.innerHTML += e.data; + logBox.scrollTop = logBox.scrollHeight; + }); + + es.onerror = () => { + es.close(); + document.getElementById('status').innerHTML = '连接中断'; + btn.disabled = false; + btn.textContent = '开始处理'; + }; + + } catch (e) { + alert('请求失败: ' + (e.message || '未知错误')); + btn.disabled = false; + btn.textContent = '开始处理'; + document.getElementById('status').innerHTML = '失败'; + } +} + +// ---- 下载链接 ---- +function showDownloadLinks(result) { + const section = document.getElementById('download-section'); + const box = document.getElementById('download-links'); + const warn = document.getElementById('doc-fill-warning'); + if (!section || !box) return; + + const items = []; + if (result.csv_url) items.push({ label: 'invoice_summary.csv', url: result.csv_url }); + if (result.md_url) items.push({ label: 'invoice_summary.md', url: result.md_url }); + if (result.doc_url) items.push({ label: '易耗品、出库单.doc', url: result.doc_url }); + + lastDownloadUrls = {}; + items.forEach(it => { lastDownloadUrls[it.label] = it.url; }); + + box.innerHTML = items.map(it => + `${it.label}` + ).join(''); + + if (warn) { + if (result.doc_ok === false && result.doc_error) { + warn.style.display = 'block'; + warn.textContent = '出库单未生成:' + result.doc_error; + } else { + warn.style.display = 'none'; + warn.textContent = ''; + } + } + + section.style.display = items.length || (result.doc_ok === false) ? 'block' : 'none'; +} + +// ---- 发票数据编辑 ---- +async function loadInvoiceData() { + try { + const r = await fetch(`/api/data/${sessionId}`); + const d = await r.json(); + if (d.error) return; + + csvFilename = d.csv_filename || 'invoice_summary.csv'; + invoiceData = d.data || []; + const fields = d.fields || Object.keys(invoiceData[0] || {}).filter(k => !k.startsWith('__')); + renderTable(invoiceData, fields); + + // 渲染后自动将配置区的工号/公务卡号同步到表格 + syncConfigToTable('工号'); + syncConfigToTable('公务卡号'); + } catch (e) { /* ignore */ } +} + +// 配置区 → 表格的同步映射:工号 ↔ cfg-username,公务卡号 ↔ cfg-card +const CONFIG_SYNC = { + '工号': 'cfg-username', + '公务卡号': 'cfg-card', +}; + +// 从配置区输入框的值更新到所有表格行 +function syncConfigToTable(field) { + const inputId = CONFIG_SYNC[field]; + if (!inputId) return; + const val = document.getElementById(inputId).value || ''; + invoiceData.forEach((row, i) => { + row[field] = val; + }); + // 更新表格中对应单元格的显示 + const tbody = document.getElementById('invoice-tbody'); + if (!tbody) return; + const rows = tbody.querySelectorAll('tr'); + rows.forEach((tr, i) => { + const inputs = tr.querySelectorAll('input'); + fieldsCache.forEach((f, colIdx) => { + if (f === field && inputs[colIdx]) { + inputs[colIdx].value = val; + } + }); + }); +} + +let fieldsCache = []; // renderTable 渲染后的字段列表,用于定位列索引 + +function renderTable(data, fields) { + const section = document.getElementById('edit-section'); + if (!data.length) { section.style.display = 'none'; return; } + section.style.display = 'block'; + + // 使用后端返回的字段顺序, fallback 到 Object.keys + if (!fields || !fields.length) { + fields = Object.keys(data[0]).filter(k => !k.startsWith('__')); + } + fieldsCache = fields; + + // 表头 + document.getElementById('invoice-thead').innerHTML = ` + + # + ${fields.map(f => `${f}`).join('')} + + `; + + // 表体:每行首列为序号,其后为各字段 input + const rows = data.map((row, i) => { + const cells = fields.map(f => { + let onChangeStr = `invoiceData[${i}]['${f.replace(/'/g, "\\'")}']=this.value`; + // 如果该字段参与配置区同步,额外调用 syncTableToConfig + if (CONFIG_SYNC[f]) { + onChangeStr += `;syncTableToConfig('${f.replace(/'/g, "\\'")}', this.value)`; + } + return ``; + }).join(''); + return `${i + 1}${cells}`; + }).join(''); + + document.getElementById('invoice-tbody').innerHTML = rows; +} + +// 从表格修改同步回配置区 +function syncTableToConfig(field, value) { + const inputId = CONFIG_SYNC[field]; + if (inputId) { + document.getElementById(inputId).value = value; + } +} + +function escapeHtml(s) { + return s.replace(/&/g,'&').replace(//g,'>').replace(/"/g,'"'); +} + +// 将当前表格编辑内容写回服务器(内部调用) +async function saveInvoiceData() { + try { + const r = await fetch(`/api/save/${sessionId}`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ data: invoiceData, csv_filename: csvFilename }), + }); + const d = await r.json(); + if (d.doc_url || d.doc_ok === false) { + showDownloadLinks({ + csv_url: lastDownloadUrls['invoice_summary.csv'], + md_url: lastDownloadUrls['invoice_summary.md'], + doc_url: d.doc_url, + doc_ok: d.doc_ok, + doc_error: d.doc_error, + }); + } + } catch (e) { + console.warn('自动保存失败,继续提交:', e); + } +} + +// ---- 提交到财务系统 ---- +async function submitFinancial() { + const btn = document.getElementById('btn-submit'); + btn.disabled = true; + btn.textContent = '提交中...'; + document.getElementById('log-box').innerHTML = ''; + + try { + // 提交前先自动保存当前表格编辑内容 + await saveInvoiceData(); + + await fetch(`/api/submit-financial/${sessionId}`, { method: 'POST' }); + + // 监听日志流(复用 SSE) + const es = new EventSource(`/api/logs/${sessionId}`); + const logBox = document.getElementById('log-box'); + let firstLine = true; + + es.addEventListener('message', e => { + if (firstLine) { logBox.innerHTML = ''; firstLine = false; } + try { + const msg = JSON.parse(e.data); + if (msg.type === 'done') { + es.close(); + btn.disabled = false; + const result = msg.result; + if (result && result.submit_ok) { + btn.textContent = '✅ 提交完成'; + setTimeout(() => { btn.textContent = '🚀 提交到财务系统'; }, 3000); + } else { + const errorMsg = result?.submit_error || result?.error || '未知错误'; + btn.textContent = '❌ 提交失败'; + logBox.innerHTML += `
❌ 提交失败:${errorMsg}
`; + logBox.scrollTop = logBox.scrollHeight; + console.warn('提交失败:', errorMsg); + setTimeout(() => { btn.textContent = '🚀 提交到财务系统'; }, 5000); + } + return; + } + } catch (err) {} + logBox.innerHTML += e.data; + logBox.scrollTop = logBox.scrollHeight; + }); + + es.onerror = () => { + es.close(); + btn.disabled = false; + btn.textContent = '🚀 提交到财务系统'; + }; + } catch (e) { + alert('提交失败: ' + e.message); + btn.disabled = false; + btn.textContent = '🚀 提交到财务系统'; + } +} + +// ---- 二维码 / 手机扫码上传 ---- +let qrGenerated = false; +let syncTimer = null; + +async function generateQr() { + await ensureSession(); + const mobileUrl = window.location.origin + '/mobile/' + sessionId; + const box = document.getElementById('qrcode'); + box.innerHTML = ''; + new QRCode(box, { + text: mobileUrl, + width: 120, + height: 120, + colorDark: '#333', + colorLight: '#fff', + }); + qrGenerated = true; +} + +// ---- 实时同步:轮询服务器文件列表,检测手机端上传的新图片 ---- +async function startSync() { + if (syncTimer) return; + await syncFiles(); + syncTimer = setInterval(syncFiles, 3000); +} + +function stopSync() { + if (syncTimer) { clearInterval(syncTimer); syncTimer = null; } +} + +async function syncFiles() { + if (!sessionId) return; + try { + const r = await fetch(`/api/files/${sessionId}`); + const d = await r.json(); + const serverNames = new Set(d.images || []); + const localNames = new Set(imgFiles.map(f => f.name)); + + for (const name of serverNames) { + if (!localNames.has(name)) { + const resp = await fetch(`/api/download/${sessionId}/${encodeURIComponent(name)}`); + const blob = await resp.blob(); + const file = new File([blob], name, { type: blob.type }); + file.__source = 'server'; // 标记为扫码上传 + imgFiles.push(file); + } + } + + // 只清理来自服务器但已不存在的文件,保留本地手动选择的文件 + for (const f of [...imgFiles]) { + if (!serverNames.has(f.name) && f.__source !== 'local') { + const idx = imgFiles.indexOf(f); + if (idx > -1) imgFiles.splice(idx, 1); + } + } + + renderFileList('img'); + if (imgFiles.length) { + document.getElementById('img-zone').classList.add('active'); + } else { + document.getElementById('img-zone').classList.remove('active'); + } + } catch (e) { /* ignore */ } +} + +generateQr(); +startSync(); + +// ---- 配置区 → 表格的双向同步绑定 ---- +Object.values(CONFIG_SYNC).forEach(inputId => { + const el = document.getElementById(inputId); + if (el) { + el.addEventListener('input', () => { + // 根据 inputId 反查对应的字段名 + const field = Object.entries(CONFIG_SYNC).find(([, id]) => id === inputId)?.[0]; + if (field) syncConfigToTable(field); + }); + } +}); \ No newline at end of file diff --git a/web/templates/index.html b/web/templates/index.html index affac5b..4c516fc 100644 --- a/web/templates/index.html +++ b/web/templates/index.html @@ -5,26 +5,7 @@ 财务报销自动化 - + @@ -103,11 +84,9 @@ body { background: #f5f7fa; } -
-
- - -
+
+ +
@@ -119,10 +98,32 @@ body { background: #f5f7fa; } - -
-
📊 处理结果
-
+ + + + + @@ -132,307 +133,6 @@ body { background: #f5f7fa; }
- + \ No newline at end of file diff --git a/易耗品、出库单.doc b/易耗品、出库单.doc new file mode 100644 index 0000000000000000000000000000000000000000..d683b75770eece31c5f8c5f015051defe274fb2e GIT binary patch literal 122368 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 iPU2q*