302 lines
10 KiB
Markdown
302 lines
10 KiB
Markdown
# 阜阳师范大学财务报销系统 - 自动化脚本操作指南
|
||
|
||
> 适用场景:日常报销录入(基于 `reimburse.py` 脚本)
|
||
> 最后更新:2026-05-23
|
||
|
||
---
|
||
|
||
## 一、系统概览
|
||
|
||
```
|
||
整体流程:
|
||
|
||
信息门户(SSO登录) → 财务系统入口 → 单点登录页 → 网络报销 → 日常报销录入
|
||
(tyrz.fynu.edu.cn) (点击"财务系统") (新标签页) (a:has(img)) (/expen/common/common)
|
||
|
||
目标系统: http://210.45.32.214:8081
|
||
用户: 王建锋 (工号: 202407021)
|
||
```
|
||
|
||
### 关键 URL
|
||
|
||
| 系统 | URL | 说明 |
|
||
|------|-----|------|
|
||
| SSO 登录 | `https://tyrz.fynu.edu.cn/sso/login` | 统一认证入口 |
|
||
| 信息门户 | `https://tyrz.fynu.edu.cn/oshall` | 登录后跳转目标 |
|
||
| 报销系统 | `http://210.45.32.214:8081` | 网络报销主系统 |
|
||
| 日常报销录入 | `/expen/common/common?v=4.0` | 目标录入页面 |
|
||
|
||
---
|
||
|
||
## 二、数据准备
|
||
|
||
### 2.1 发票数据 CSV
|
||
|
||
脚本从 `invoice_summary.csv`(GBK 编码)读取发票数据,CSV 需包含以下列:
|
||
|
||
| 列名 | 说明 | 示例 |
|
||
|------|------|------|
|
||
| 序号 | 发票序号 | 1, 2, 3... |
|
||
| 发票号码 | 发票编号 | 26442000005432652421 |
|
||
| 开票日期 | 发票开具日期 | 2026/5/18 |
|
||
| 项目名称 | 采购项目名称 | 电阻一批 |
|
||
| 规格型号 | 规格型号 | — |
|
||
| 价税合计 | 发票金额 | 2900.00 |
|
||
| 销售方名称 | 商户/销售方 | 佛山市泓宇芯科技有限公司 |
|
||
| 人员姓名 | 报销人 | 王建锋(默认值) |
|
||
| 刷卡日期 | 公务卡消费日期 | 2026/5/18 → 自动转为 2026-05-18 |
|
||
| 公务卡号 | 公务卡卡号 | 6282880139161682(默认值) |
|
||
| 刷卡金额 | 实际刷卡金额 | 2900.00 |
|
||
| 备注 | 备注信息 | — |
|
||
| 工号 | 人员工号 | 202407021(默认值) |
|
||
|
||
### 2.2 附件文件
|
||
|
||
脚本自动扫描当前工作目录下所有 `.pdf` 文件,按文件名排序后与发票一一对应上传。确保 PDF 文件名与发票顺序一致。
|
||
|
||
---
|
||
|
||
## 三、脚本执行流程
|
||
|
||
### 运行方式
|
||
|
||
```bash
|
||
python reimburse.py --data invoice_summary.csv
|
||
```
|
||
|
||
支持命令行覆盖配置:
|
||
|
||
```bash
|
||
python reimburse.py \
|
||
--data invoice_summary.csv \
|
||
--username 202407021 \
|
||
--password "your_password" \
|
||
--user-data-dir browser_profile
|
||
```
|
||
|
||
### 执行步骤
|
||
|
||
脚本按以下顺序自动执行,截图保存在 `images/` 目录:
|
||
|
||
```
|
||
Step 0: 登录信息门户
|
||
├── 访问 SSO 登录页
|
||
├── 填写工号 + 密码
|
||
├── 勾选用户协议复选框
|
||
├── 点击"登录"按钮
|
||
└── 等待跳转到信息门户 (zs-uip/oshall/portal)
|
||
|
||
Step 1: 进入报销系统
|
||
├── 点击"财务系统"快捷入口
|
||
├── 等待新标签页打开 (含 dddl 或 210.45.32.214)
|
||
├── 切换到新标签页
|
||
├── 关闭旧标签页
|
||
├── 通过 a:has(img[src*="wlbx"]) 定位"网络报销"链接
|
||
├── 提取链接 URL 并导航
|
||
├── 等待"报销录入"文本出现
|
||
└── 导航到 /expen/common/common?v=4.0
|
||
|
||
Step 2: 创建新报销单
|
||
├── 等待 2 秒
|
||
├── 点击 button:has-text("新增")
|
||
└── 等待表单加载 3 秒
|
||
|
||
Step 3: 填写基本信息
|
||
├── 填写 #EXPENEXPLAIN → "元器件采购报销"
|
||
├── 点击 #PROJECTCODE 打开项目选择弹窗
|
||
├── 在 #promodal .fixed-table-body tbody tr 中点击第一行
|
||
└── 点击 #saveAndNext 进入下一步
|
||
|
||
Step 4: 录入报销明细(一条总明细)
|
||
├── 计算所有发票的刷卡金额合计
|
||
├── 点击 #insertDetail 打开增加明细弹窗
|
||
├── 点击 #economicscode2 打开经济科目选择
|
||
├── 在 #econmodal 中选择第 3 行经济科目
|
||
├── 填写单据数 = 发票张数
|
||
├── 填写报销总金额 = 刷卡金额合计
|
||
└── 点击 #detailAdd 确认
|
||
|
||
Step 5: 录入支付方式(逐张发票)
|
||
├── 点击 "下一步(支付方式)"
|
||
├── 对每张发票循环:
|
||
│ ├── 点击 #insertPay
|
||
│ ├── 填写 #personid2 (工号)
|
||
│ ├── 填写 #accountname2 (姓名)
|
||
│ ├── 填写 #receiptdate2 (刷卡日期)
|
||
│ ├── 填写 #localaccount2 (固定卡号: 6282880139161682)
|
||
│ ├── 填写 #receiptmoney2 (刷卡金额)
|
||
│ ├── 填写 #money2 (实报金额 = 刷卡金额)
|
||
│ ├── 填写 #merchant2 (销售方名称)
|
||
│ ├── 填写 #smark2 (备注)
|
||
│ └── 点击 #payAdd 确认
|
||
└── 所有发票录入完成
|
||
|
||
Step 6: 上传附件(逐张发票)
|
||
├── 点击 #next3 切换到附件清单页面
|
||
├── 对每张发票循环:
|
||
│ ├── 点击 #insertAcc 打开附件弹窗
|
||
│ ├── select_option #fjlx → '1' (发票类型)
|
||
│ ├── 填写 #fpsmxx (项目名称 - 发票号码)
|
||
│ ├── set_input_files #file (对应 PDF 文件)
|
||
│ └── 点击 #cjtj 确认
|
||
└── 所有附件上传完成
|
||
|
||
提交阶段:
|
||
└── 点击 #submit (当前已注释,需手动取消注释)
|
||
```
|
||
|
||
---
|
||
|
||
## 四、页面元素速查
|
||
|
||
### 基本信息页 (Step 3)
|
||
|
||
| 字段 | 选择器 | 操作 |
|
||
|------|--------|------|
|
||
| 报销说明 | `#EXPENEXPLAIN` | fill |
|
||
| 项目代码 | `#PROJECTCODE` | click → 弹窗选择 |
|
||
| 项目弹窗 | `#promodal .fixed-table-body tbody tr` | 点击第一行 |
|
||
| 下一步按钮 | `#saveAndNext` | click |
|
||
|
||
### 报销明细页 (Step 4)
|
||
|
||
| 字段 | 选择器 | 操作 |
|
||
|------|--------|------|
|
||
| 增加按钮 | `#insertDetail` | click |
|
||
| 经济事项代码 | `#economicscode2` | click → 弹窗选择 |
|
||
| 经济科目弹窗 | `#econmodal .fixed-table-body tbody tr` | 点击第 3 行 |
|
||
| 单据数 | `input[name="expenPwCommondetail.HOWBILLS"]` | fill |
|
||
| 报销总金额 | `#je_zwzcdz` | fill |
|
||
| 确定按钮 | `#detailAdd` | click |
|
||
|
||
### 支付方式页 (Step 5)
|
||
|
||
| 字段 | 选择器 | 操作 |
|
||
|------|--------|------|
|
||
| 增加按钮 | `#insertPay` | click |
|
||
| 人员编号 | `#personid2` | fill |
|
||
| 人员姓名 | `#accountname2` | fill |
|
||
| 刷卡日期 | `#receiptdate2` | fill |
|
||
| 公务卡号 | `#localaccount2` | fill (固定值) |
|
||
| 刷卡金额 | `#receiptmoney2` | fill |
|
||
| 实报金额 | `#money2` | fill |
|
||
| 商户 | `#merchant2` | fill |
|
||
| 备注 | `#smark2` | fill |
|
||
| 确定按钮 | `#payAdd` | click |
|
||
|
||
### 附件清单页 (Step 6)
|
||
|
||
| 字段 | 选择器 | 操作 |
|
||
|------|--------|------|
|
||
| 增加按钮 | `#insertAcc` | click |
|
||
| 附件类型 | `#fjlx` | select_option → '1'(发票) |
|
||
| 附件说明 | `#fpsmxx` | fill |
|
||
| 文件上传 | `#file` | set_input_files |
|
||
| 确定按钮 | `#cjtj` | click |
|
||
|
||
### 提交
|
||
|
||
| 操作 | 选择器 |
|
||
|------|--------|
|
||
| 提交按钮 | `#submit` |
|
||
| 提交按钮(备用) | `#submit2` |
|
||
|
||
---
|
||
|
||
## 五、数据流向
|
||
|
||
```
|
||
invoice_summary.csv (GBK)
|
||
│
|
||
▼ load_invoice_data()
|
||
│
|
||
├── 读取 CSV 行
|
||
├── 日期格式转换 (2026/5/18 → 2026-05-18)
|
||
├── 填充默认值 (姓名/卡号/工号)
|
||
└── 输出: list[dict]
|
||
│
|
||
▼ add_reimburse_items()
|
||
├── 计算: card_amount = sum(所有发票刷卡金额)
|
||
├── 单据数 = len(invoices)
|
||
└── 录入 1 条总明细
|
||
│
|
||
▼ fill_payment()
|
||
└── 对每张发票录入 1 条支付记录
|
||
│
|
||
▼ upload_attachments()
|
||
├── 扫描 *.pdf 文件
|
||
└── 按索引匹配发票 → PDF,逐张上传
|
||
```
|
||
|
||
---
|
||
|
||
## 六、关键设计说明
|
||
|
||
### 6.1 浏览器复用
|
||
|
||
脚本使用 `launch_persistent_context` 持久化浏览器上下文,登录状态保存在 `browser_profile/` 目录。再次运行时复用已有会话,无需重复登录。
|
||
|
||
### 6.2 明细录入策略
|
||
|
||
脚本采用"一条总明细"策略:将所有发票合并为一条报销明细,报销总金额为所有发票刷卡金额之和,单据数为发票总张数。支付方式则逐张发票分别录入,每张发票对应一条支付记录。
|
||
|
||
### 6.3 经济科目选择
|
||
|
||
脚本在经济科目弹窗中固定选择第 3 行。如需更改科目,修改 `rows[2]` 的索引即可。
|
||
|
||
### 6.4 项目选择
|
||
|
||
脚本在项目选择弹窗中固定选择第 1 行。如需更改项目,修改 `first_row` 的选择逻辑即可。
|
||
|
||
### 6.5 网络报销链接动态获取
|
||
|
||
单点登录页的"网络报销"链接参数每次不同,脚本通过 `a:has(img[src*="wlbx"])` 精确定位链接,动态提取 `href` 属性后导航,不硬编码 URL。
|
||
|
||
### 6.6 提交控制
|
||
|
||
脚本默认注释了 `bot.submit()` 调用。完成所有录入后停留在附件清单页面,需人工确认数据无误后,取消注释 `bot.submit()` 再运行,或手动点击提交按钮。
|
||
|
||
---
|
||
|
||
## 七、日志与调试
|
||
|
||
### 日志输出
|
||
|
||
- 控制台实时输出(DEBUG 级别)
|
||
- 文件日志:`reimburse.log`(UTF-8 编码)
|
||
|
||
### 截图保存
|
||
|
||
每个关键步骤自动截图到 `images/` 目录:
|
||
|
||
| 截图文件 | 对应步骤 |
|
||
|----------|----------|
|
||
| `debug_portal_loaded.png` | 登录成功 |
|
||
| `debug_step3_project_modal.png` | 项目弹窗打开 |
|
||
| `debug_step3_project_selected.png` | 项目选择完成 |
|
||
| `debug_step3_done.png` | 基本信息完成 |
|
||
| `debug_after_add_click.png` | 点击新增后 |
|
||
| `debug_item_total.png` | 总明细录入完成 |
|
||
| `debug_step5_done.png` | 支付方式完成 |
|
||
| `debug_step6_done.png` | 附件上传完成 |
|
||
| `debug_submitted.png` | 提交完成 |
|
||
| `debug_error.png` | 异常状态 |
|
||
|
||
### 超时设置
|
||
|
||
- 页面默认超时:30 秒
|
||
- 登录门户等待:最多 30 秒
|
||
- 单点登录页等待:最多 15 秒
|
||
|
||
---
|
||
|
||
## 八、常见问题
|
||
|
||
| 问题 | 原因 | 解决方案 |
|
||
|------|------|----------|
|
||
| 登录超时 | SSO 需要手动验证码/微信扫码 | 手动完成验证后脚本继续 |
|
||
| 未找到财务系统入口 | 门户页面结构变化 | 检查 `images/debug_*` 截图定位 |
|
||
| 经济科目选择失败 | 弹窗加载延迟 | 检查超时设置,增加等待时间 |
|
||
| 附件上传失败 | PDF 文件不存在或路径错误 | 确认 PDF 在当前工作目录 |
|
||
| 金额不匹配 | 明细合计 ≠ 支付合计 | 检查 CSV 数据中刷卡金额 |
|
||
| 提交被拦截 | 必填项为空 | 检查 `reimburse.log` 定位失败步骤 | |