wlzh-invoice-scanner

star 572

扫描目录识别所有类型发票(交通、住宿、餐饮等),提取关键信息并生成分类统计报告

wlzh By wlzh schedule Updated 6/10/2026

name: wlzh-invoice-scanner description: 扫描目录识别所有类型发票(交通、住宿、餐饮等),提取关键信息并生成分类统计报告 version: 3.7.0 author: wlzh changelog: - "3.7.0: 新增首次使用指南,补充第一次拿到 Skill 时的准备、调用、模式选择、输出文件、统一汇总配置说明;文档示例路径脱敏" - "3.6.0: 新增招待费/客户模式;输入包含招待费、招待或客户时逐张输出招待费明细,不汇总发票号和金额;补充 Windows 路径配置说明" - "3.5.0: 新增报销汇总追加功能;config.json 配置汇总文件路径,每次扫描后自动将摘要卡片追加到汇总 MD 最上面" - "3.4.0: 金额展示格式改为无千分位逗号,并去掉小数尾随 0,便于复制粘贴到不接受逗号的系统" - "3.3.0: 新增结构化摘要卡片输出(文件夹名/总金额/发票号汇总/分类明细)" - "3.2.0: 新增退票费独立分类(火车退票费/机票退票费);五大分类替代四大分类" - "3.1.0: 强制 Python 算术校验;铁路客票一律归长途交通;报告文件名改为文件夹名.md;增加重复发票去重逻辑;增加处理前重新扫描要求" - "3.0.0: 铁路电子客票归长途交通;报告文件名改为文件夹名" - "2.5.0: 初始完整版本"

发票扫描器

你是一个专业的发票识别专家。任务是识别和提取各类发票的关键信息,并按类型分类统计。

用法示例

/wlzh-invoice-scanner ./发票文件夹
/wlzh-invoice-scanner ./receipts.zip

# Windows 路径建议加引号;JSON 配置中反斜杠需写成 \\\\,命令输入可直接使用 Windows 路径
/wlzh-invoice-scanner "C:\\Users\\Alice\\Documents\\发票"
/wlzh-invoice-scanner "C:\\Users\\Alice\\Documents\\receipts.zip"

# 招待费/客户模式:输入路径或附加提示包含「招待费」「招待」「客户」任一关键词即启用
/wlzh-invoice-scanner ./客户发票
/wlzh-invoice-scanner ./餐饮发票 招待
/wlzh-invoice-scanner "C:\\Users\\Alice\\Documents\\客户招待" 招待费

工作流程

1. 接收参数

  • 用户会提供一个目录路径或 ZIP 文件路径
  • 默认路径是当前工作目录
  • 记录原始输入路径,用于后续保存报告
  • 路径包含空格、括号或 Windows 盘符时,建议用引号包住,例如:/wlzh-invoice-scanner "C:\\Users\\Alice\\Documents\\发票"

1.1 模式判定(默认统计模式 / 招待费客户模式)

默认行为不变:如果输入路径和附加参数都不包含触发词,继续执行原有完整发票统计逻辑(分类、发票号汇总、金额累加、Python 校验、结构化摘要卡片)。

招待费/客户模式触发条件:仅根据用户本次输入判断,不根据发票内容自动猜测。检查原始输入路径和路径后的附加提示,只要包含以下任一关键词即启用招待费/客户模式:

  • 招待费
  • 招待
  • 客户

示例:

/wlzh-invoice-scanner ./客户发票
/wlzh-invoice-scanner ./餐饮发票 招待
/wlzh-invoice-scanner ./receipts.zip 招待费

招待费/客户模式下,每张发票独立输出为一条 招待费 明细;不生成发票号汇总,不进行金额累计,不输出分类统计

2. 文件扫描与预处理

2.1 清理无用文件(第一步)

在开始扫描之前,先清理目录中的无用文件:

  • 使用 Bash 工具查找并删除:find "<input_dir>" -type f \( -name "*.xml" -o -name "*.ofd" \) -delete
  • 输出提示:已清理 X 个无用文件(.xml, .ofd)

2.2 处理 ZIP 文件

接收输入路径后,判断类型并处理:

情况A:输入是 ZIP 文件

  1. 获取 ZIP 文件所在的目录路径(报告将保存在这里)
  2. 创建临时目录:/tmp/invoice_scanner_<timestamp>
  3. 解压 ZIP 文件到临时目录:unzip -q "<zipfile>" -d "<temp_dir>"
  4. 将临时目录中的所有文件(不含子文件夹结构)移动到报告目录:
    • 使用命令:find "<temp_dir>" -type f -exec mv {} "<report_dir>/" \;
  5. 删除临时目录:rm -rf "<temp_dir>"
  6. 删除原始 ZIP 文件:rm -f "<zipfile>"
  7. 输出提示:已解压并清理 ZIP 文件

情况B:输入是目录

  1. 首先检测目录中是否包含 ZIP 文件

    • 使用 Bash 查找:find "<input_dir>" -name "*.zip"
    • 如果找到 ZIP 文件,进入自动解压流程
  2. 自动解压 ZIP 文件(如果存在)

    • 对找到的每个 ZIP 文件:
      • 在 ZIP 文件所在的同级目录创建临时解压目录
      • 使用命令:unzip -q "<zip_file>" -d "<temp_extract_dir>"
      • 将解压出的所有文件(不含文件夹结构)移动到 ZIP 所在目录:
        • find "<temp_extract_dir>" -type f -exec mv {} "<zip_parent_dir>/" \;
      • 删除临时解压目录:rm -rf "<temp_extract_dir>"
      • 删除原始 ZIP 文件:rm -f "<zip_file>"
    • 输出提示:已解压并清理 X 个 ZIP 文件

2.3 扫描发票文件

  • 每次处理前必须重新扫描目录,不依赖任何旧报告或缓存
  • 递归扫描输入目录及所有子目录中的图片文件
  • 文件类型:*.jpg, *.jpeg, *.png, *.pdf
  • 使用 Bash 查找:find "<input_dir>" -type f \( -name "*.jpg" -o -name "*.jpeg" -o -name "*.png" -o -name "*.pdf" \) | sort
  • 输出文件列表和数量

3. 发票识别与分类

对每个文件:

  • 使用 Read 工具读取图片/PDF 内容
  • 分析内容判断发票类型,分为以下五大类:

A. 市内交通发票

  • 🚕 打车发票(滴滴、出租车、网约车等)
  • 🚇 地铁票、公交票

B. 长途交通发票 ⚠️ 铁路电子客票一律归此类

  • 🛫 飞机票(机票行程单、电子客票行程单)
  • 🚄 火车票(高铁、动车、普通列车、城际列车 — 所有铁路电子客票,不论距离长短
  • 🚌 长途汽车票

⚠️ 分类硬规则(v3.1 起强制执行):票据类型为"铁路电子客票"→ 一律归"长途交通"。市内交通仅限出租车/网约车发票、地铁票、公交票。即使行程是短途(如樟木头→深圳、深圳北→樟木头),铁路电子客票也归长途交通。

C. 住宿发票

  • 🏨 酒店住宿发票
  • 🏠 酒店结账单(仅作佐证,不重复计费)
  • 增值税专用发票(住宿服务)

D. 退票费 ⚠️ 独立分类(v3.2 起新增)

  • 🎫 火车退票费(改签/退票产生的手续费、差额退票费)
  • ✈️ 机票退票费(机票退改签手续费)
  • 识别标志:票据上标注"退票费"、"改签费"、"退票手续费"、"差额退票"等字样
  • 注意:退票费金额通常为负数或较小的正数,与其他交通费用分开统计

E. 其他发票

  • 🍽️ 餐饮发票
  • 📱 通讯费发票
  • 📦 办公用品、快递等其他消费
  • ❌ 非发票文件(个人转账、支付记录等不计入统计)

4. 重复发票去重

⚠️ 必须在识别阶段执行去重,避免重复计费

去重规则:

  1. 按发票号码去重:如果两个文件有相同的发票号码,只计入一次
  2. 行程单 vs 电子发票:滴滴行程报销单、弘扬行程单是电子发票的辅助凭证,不单独计费
  3. 结账单 vs 住宿发票:酒店结账单是住宿发票的辅助凭证,不单独计费
  4. 文件名 _1 后缀:通常表示重复下载/打印的同一张发票

标记方式:

  • 计入的发票标记为 计入: 是
  • 重复/佐证文件标记为 计入: 否,并注明对应的正式发票号码

5. 信息提取

根据发票类型提取关键字段:

A. 市内交通发票字段:

  • 分类: "市内交通"
  • 具体类型: "打车" / "地铁" / "公交"
  • 日期
  • 时间
  • 起点(如有)
  • 终点(如有)
  • 距离(公里,如有)
  • 金额
  • 平台/公司(滴滴、出租车等)
  • 发票号码(如有)
  • 文件路径

B. 长途交通发票字段:

飞机票:

  • 分类: "长途交通"
  • 具体类型: "飞机票"
  • 乘客姓名
  • 航班号
  • 出发地(城市+机场)
  • 目的地(城市+机场)
  • 日期(起飞日期)
  • 时间(起飞时间)
  • 金额(合计,含票价+燃油+税费+民航基金)
  • 票价明细(票价/燃油附加费/增值税/民航发展基金)
  • 发票号码
  • 电子客票号码
  • 文件路径

火车票:

  • 分类: "长途交通"
  • 具体类型: "火车票"
  • 乘客姓名
  • 车次
  • 出发站
  • 到达站
  • 日期
  • 时间
  • 座位类型(一等座、二等座等)
  • 金额
  • 发票号码
  • 电子客票号
  • 文件路径

C. 住宿发票字段:

  • 分类: "住宿"
  • 具体类型: "酒店发票" / "酒店结账单"
  • 酒店名称
  • 客人姓名(如有)
  • 房间号(如有)
  • 入住日期
  • 离店日期
  • 天数
  • 金额
  • 发票号码
  • 发票类型(增值税专用/普通发票)
  • 文件路径

D. 退票费字段:

  • 分类: "退票费"
  • 具体类型: "火车退票费" / "机票退票费"
  • 乘客姓名
  • 原车次/航班号(如有)
  • 日期
  • 金额
  • 发票号码
  • 退票原因/说明
  • 文件路径

E. 其他发票字段:

  • 分类: "其他"
  • 具体类型: "餐饮" / "通讯" / "办公用品" / "快递" / "其他"
  • 商户/服务商名称
  • 日期
  • 金额
  • 发票号码(如有)
  • 项目/服务内容描述
  • 文件路径

5.1 招待费/客户模式字段(输入含 招待费 / 招待 / 客户 时)

招待费/客户模式不再按五大分类输出,而是每张正式发票单独一行。多张发票必须写多行,不合并。

每张发票提取字段:

  • 费用名称:固定为 招待费
  • 发票号码
  • 金额(仍使用复制友好格式,如 ¥268¥520.5
  • 餐厅/商户名称
  • 开票日期(如有)
  • 文件路径
  • 备注(字段不确定、重复、非正式发票等)

餐厅/商户名称提取优先级:

  1. 优先取 销售方名称 / 商户名称 / 餐厅名称 / 服务商名称
  2. 如果没有明确字段,取票面上最可信的餐饮商户名称
  3. 如果仍不确定,写 待确认,并在备注中标注 ⚠️ 餐厅/商户名称存疑,请人工复核

招待费/客户模式仍需二次确认每张发票的发票号码、金额、餐厅/商户名称;无法确认的字段标记为 待确认 或添加 ⚠️ 备注。

6. 发票字段提取确认机制

⚠️ 关键步骤:每张发票提取后必须进行二次确认,确保准确性

6.1 重点确认项

发票号码确认:

  • 发票号码通常是一串数字(如:20位数字)
  • 如果不确定,标注为"待确认"并在备注中说明

金额确认:

  • 优先提取"价税合计"或"总金额"
  • 确认数字、小数点位置完全正确
  • 转换为数字后保留2位小数用于计算校验
  • 展示金额时使用复制友好格式:不加千分位逗号,去掉小数尾随 0;例如 ¥1277¥44.2¥400.5¥0。不要输出 ¥1,277.00¥44.20¥400.50¥0.00

日期确认:

  • 确认日期格式正确(YYYY-MM-DD)
  • 对于机票/火车票,确认是出发日期而非购买日期

6.2 异常处理

如果确认时发现问题:

  • 重新读取发票图片进行二次提取
  • 如果仍然无法确认,在发票记录中添加标记:
    备注: ⚠️ 字段提取存疑,请人工复核
    

7. 金额计算验证逻辑 ⚠️ 核心防错机制

⚠️ 极其重要:LLM 心算经常出错(如 1837+222.58+1393.04 算成 3052 而非 3452),必须用代码验证

招待费/客户模式不输出总金额、分类小计和金额累加结果,因此跳过“总额/分类合计”校验;但每张发票金额仍必须逐张二次确认,并使用复制友好金额格式展示。

7.1 提取阶段

  • 所有金额必须转换为浮点数(保留2位小数)
  • 如果提取失败,计算值设为 0.00,并在备注中标注 "金额提取失败";面向用户展示时写作 ¥0

7.2 默认统计模式校验阶段(必须执行,不可跳过)

生成报告后,必须使用 Bash 工具运行 Python 进行独立算术校验:

python3 -c "
items = [<所有发票金额列表,用逗号分隔>]
total = sum(items)
print(f'单张合计: {total:.2f}')
print(f'报告总额: <报告中的总额>')
print(f'校验: {\"✓\" if abs(total - <报告总额>) < 0.02 else \"✗ 差异!\"}')"

校验规则:

  • 单张金额合计 === 总金额(允许误差 ±0.02 元)
  • 市内交通 + 长途交通 + 住宿 + 退票费 + 其他 === 总金额
  • 如果校验失败,必须重新计算并修正报告,直到校验通过
  • 在报告中添加校验标记:✓ 金额已校验

7.3 长途交通费用合并规则

  • 飞机票 + 火车票 + 长途汽车票 = 长途交通合计
  • 在统计输出中必须显示:
    • 长途交通合计(飞机+火车+长途汽车的总和)
    • 每个子类型的明细(飞机票、火车票各自的数量和金额)

7.4 金额展示格式(复制友好)

所有面向用户的金额展示(报告正文、表格、统计摘要、金额验证、结构化摘要卡片)都必须使用复制友好格式:

  • 禁止千分位逗号:¥1277,不要写 ¥1,277.00
  • 去掉小数尾随 0:¥44.2,不要写 ¥44.20¥400.5,不要写 ¥400.50
  • 小数部分全为 0 时去掉小数点和两个 0:¥230,不要写 ¥230.00
  • 0 元显示为 ¥0,不要写 ¥0.00
  • 计算和 Python 校验仍保留数值精度;只有最终展示做格式化

建议使用这个 Python 格式化函数生成展示金额:

def fmt_yuan(x):
    s = f"{float(x):.2f}".rstrip('0').rstrip('.')
    return f"¥{s}"

8. 生成报告

生成 Markdown 报告文件到输入路径的目录:

  • 如果输入是 ZIP 文件,报告保存到 ZIP 文件所在的目录
  • 如果输入是目录,报告保存到该目录
  • 报告文件名:使用文件夹名称作为报告文件名,格式为 <文件夹名称>.md
    • 例如:目录 /path/to/降噪客户拜访 0518-0521 → 报告 降噪客户拜访 0518-0521.md
    • 不再使用 invoices.md
  • 压缩包名称格式不变,仍为 <文件夹名称>.zip

<文件夹名称>.md - 可读性报告,根据模式输出:

默认统计模式包含:

  1. 发票号汇总行(顶部):将所有发票号用斜杠分隔连接成一行,格式为 "发票号1/发票号2/发票号3",方便用户复制粘贴
  2. 扫描日期和目录信息
  3. 汇总统计(带金额校验标记)
    • 总金额、总发票数
    • 五大分类的数量和金额
    • ✓ 金额已校验标记
  4. 按五大分类分组的详细表格
  5. 每个发票的详细信息
  6. 重复发票说明(列出哪些文件是重复/佐证,对应哪张正式发票)
  7. 未识别文件列表(含原因说明)
  8. 需要复核的发票(如果有标记为⚠️的发票)

招待费/客户模式包含:

  1. 扫描日期、目录信息、模式说明(招待费/客户模式
  2. 每张发票一行的招待费明细表;多张发票必须写多行
  3. 明细表字段:序号费用名称发票号码金额餐厅/商户开票日期文件路径备注
  4. 每行 费用名称 固定写 招待费
  5. 未识别文件列表(含原因说明)
  6. 重复/佐证文件说明(如有)
  7. 需要复核的发票(如有)

招待费/客户模式不得输出:发票号汇总行、总金额、金额累加、五大分类统计、分类金额校验公式、默认统计摘要卡片。

发票号汇总行示例

📋 发票号汇总(可复制): 1234567890/9876543210/5555666677/8888999900

9. 清理中间文件

生成报告后,清理报告目录中的所有中间文件:

  • 使用 Bash 工具批量删除:find "<report_dir>" -type f \( -name "*.xml" -o -name "*.ofd" -o -name "*.zip" \) -delete
  • 注意:先创建最终 zip(第10步),然后再清理 zip?不——清理中间文件在打包之前执行,因为打包时会创建新 zip
  • 清理顺序:先清理旧的中间文件 → 再打包最终 zip
  • 输出提示:🗑️ 已清理 X 个中间文件(.xml, .ofd, .zip)
  • 此步骤默认统计模式和招待费/客户模式都必须执行。

10. 打包最终文件

完成所有处理后,将报告目录中的所有文件打包成一个 ZIP 压缩包(默认统计模式和招待费/客户模式都必须执行):

10.1 确定压缩包名称

  • 获取报告目录的文件夹名称(basename)
  • 压缩包名称格式:<文件夹名称>.zip
  • 例如:如果报告目录是 /path/to/发票2024,则压缩包名称为 发票2024.zip

10.2 创建压缩包

  • 在报告目录内部创建 ZIP 文件(与报告 .md 同级)
  • 使用 Bash 工具执行压缩命令:
    cd "<report_dir>" && rm -f "<folder_name>.zip" && zip -r "<folder_name>.zip" . -x "*.DS_Store" -x "<folder_name>.zip"
    
  • 参数说明:
    • -r: 递归压缩所有文件和子目录
    • .: 压缩当前目录的所有内容
    • -x "*.DS_Store": 排除 macOS 系统文件
    • -x "<folder_name>.zip": 排除 zip 文件自身,避免递归

10.3 验证压缩包

  • 检查压缩包是否成功创建
  • 获取压缩包的文件大小

10.4 输出提示

📦 已打包最终文件:<path_to_zip_file>
   压缩包大小:X.XX MB

示例

输入目录:/path/to/发票2024
生成的报告:/path/to/发票2024/发票2024.md
生成的压缩包:/path/to/发票2024/发票2024.zip

注意事项

  • 所有正式发票都应计入统计,包括电子发票、纸质发票扫描件等
  • 对于无法识别的图片或非正式发票(如支付截图、转账记录),记录到"未识别文件"部分,说明原因
  • 重复发票去重
    • 按发票号码去重,相同发票号码只计入一次
    • 行程报销单/结账单是电子发票的辅助凭证,不重复计费
    • 在报告中明确标注哪些文件是重复/佐证
  • 金额提取失败时计算值标记为 0.00,展示为 ¥0,并在备注中说明
  • 发票字段确认
    • 每张发票提取后必须二次确认发票号和金额
    • 发现提取错误时重新读取图片
    • 无法确认的字段标记"⚠️ 待人工复核"
  • 文件清理
    • 扫描前自动删除所有 .xml.ofd 文件
    • 打包前再次清理所有 .xml.ofd 和旧 .zip 文件
  • 最终打包
    • 压缩包名称以文件夹名称命名(例如:发票2024.zip
    • 压缩包保存在报告目录内部(与报告 .md 同级)
    • 排除 macOS 系统文件(.DS_Store)和 zip 文件自身
  • 报告文件名:使用文件夹名称命名(如 降噪客户拜访 0518-0521.md),不再使用 invoices.md
  • 分类硬规则
    • 铁路电子客票(火车票/高铁/动车/城际)→ 一律归"长途交通"
    • 市内交通仅限出租车/网约车发票、地铁票、公交票
    • 住宿费增值税发票 → 归入"住宿"类
    • 退票费/改签费 → 单独归入"退票费"类(v3.2 新增)
  • 完成后输出报告的完整路径和按分类的统计摘要
  • 完成后输出已处理的 ZIP 文件数量、清理的文件数量和最终压缩包路径

错误处理

  • 如果路径不存在,提示用户
  • 如果没有找到任何发票,生成空报告
  • 如果图片损坏无法读取,记录错误并继续处理其他文件

输出示例

完成后输出:

🗑️ 已清理 3 个无用文件(.xml, .ofd)
📦 已解压并清理 2 个 ZIP 文件

✅ 发票扫描完成

📊 统计摘要:
- 总计: 15 张发票
- 总金额: ¥8430.5
- ✓ 金额已校验(Python 独立验算通过)

📋 发票号汇总: 1234567890/9876543210/5555666677/8888999900

按分类统计:
📍 市内交通: 5 张 (¥230)
  - 打车: 4 张 (¥210)
  - 地铁: 1 张 (¥20)

✈️ 长途交通合计: 4 张 (¥3600)  ← 飞机+火车+长途汽车总和
  - 飞机票: 2 张 (¥2400)
  - 火车票: 2 张 (¥1200)

🏨 住宿: 2 张 (¥4200)

🎫 退票费: 0 张 (¥0)

📦 其他: 4 张 (¥400.5)
  - 餐饮: 3 张 (¥350.5)
  - 通讯: 1 张 (¥50)

💡 金额验证:
  单张合计: 230.00 + 3600.00 + 4200.00 + 0.00 + 400.50 = 8430.50
  市内交通 (¥230) + 长途交通 (¥3600) + 住宿 (¥4200) + 退票费 (¥0) + 其他 (¥400.5) = 总计 (¥8430.5) ✓

⚠️ 1 张发票需要人工复核(发票字段提取存疑)

📄 报告已生成:
- /path/to/发票2024.md

🗑️ 已清理 5 个中间文件(.xml, .ofd, .zip)

📦 已打包最终文件:/path/to/发票2024.zip
   压缩包大小:12.45 MB
   位置:报告目录内部

11. 结构化摘要卡片(必须输出)

⚠️ 处理完成后,必须在终端最后输出一个结构化摘要卡片。默认统计模式输出分类摘要卡片;招待费/客户模式输出逐张明细卡片。

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
  📂 降噪客户拜访 0518-0521
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
  💰 总金额: ¥2811.55 (7张)
  📋 发票号: 26952000002075124346/26952000002055155446/26449123774000016358/26338891111036673445/26952000002037354826/26449165860002800464/26448784110004571321

  📊 分类:
     长途交通  5张  ¥1875  (飞机票×2 ¥1820 | 火车票×3 ¥55)
     住宿     3张  ¥936.55
     退票费   0张  ¥0
     市内交通 0张  ¥0
     其他     0张  ¥0
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

默认统计模式摘要卡片要求:

  • 使用分隔线框住,视觉突出
  • 文件夹名称醒目展示
  • 发票号用斜杠分隔在一行内
  • 分类按金额从大到小排列
  • 长途交通需展开子类型(飞机票×N ¥X | 火车票×N ¥X)
  • 没有发票的分类显示 0张 ¥0

招待费/客户模式摘要卡片要求:

  • 使用分隔线框住,视觉突出
  • 文件夹名称醒目展示,并标注 模式:招待费/客户
  • 不输出总金额、不输出发票号汇总、不输出分类统计
  • 每张发票单独一行:招待费 发票号 金额 餐厅/商户
  • 多张发票必须输出多行

招待费/客户模式示例:

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
  📂 客户餐饮发票
  模式:招待费/客户
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
  招待费  1234567890  ¥268  深圳市某某餐厅
  招待费  9876543210  ¥520.5  广州市某某酒楼
  招待费  5555666677  ¥188  上海某某饭店
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
  • 这是最后一步输出,确保用户一眼看到关键信息

12. 追加汇总到配置文件(如果配置存在)

⚠️ 在步骤 11 输出摘要卡片之后执行

12.1 读取配置

  • 读取 skill 目录下的 config.json 文件
  • 路径:与 SKILL.md 同级目录下的 config.json
  • 如果文件不存在,跳过此步骤,不影响正常流程
  • 配置格式:
    {
      "summary_dir": "/path/to/baoxiao/",
      "summary_file": "报销汇总.md"
    }
    
  • Windows 路径可使用正斜杠:"C:/Users/Alice/Documents/报销/"
  • Windows 路径如使用反斜杠,JSON 中必须双写:"C:\\Users\\Alice\\Documents\\报销\\"

12.2 默认统计模式:追加摘要卡片

  • 拼接完整路径:summary_dir + summary_file
  • 如果文件不存在,创建新文件,先写入标题行:
    # 报销汇总
    
  • 如果文件已存在,读取现有内容
  • 将当前行程的摘要卡片插入到文件正文最前面(紧跟标题之后)
  • 插入格式(每条记录以日期标题开头):
# 报销汇总

## YYYY-MM-DD 文件夹名称
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
  💰 总金额: ¥XXX (N张)
  📋 发票号: xxx/xxx/xxx

  📊 分类:
     长途交通  N张  ¥XXX  (飞机票×N ¥XXX | 火车票×N ¥XXX)
     市内交通  N张  ¥XXX
     住宿     N张  ¥XXX
     退票费   N张  ¥XXX
     其他     N张  ¥XXX
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

(旧记录继续...)

12.3 招待费/客户模式:追加逐张明细

当本次输入触发招待费/客户模式时,仍然写入同一个 summary_dir + summary_file,并插入到汇总 MD 顶部(紧跟 # 报销汇总 标题之后)。

  • 每次扫描插入一个日期标题和一个明细表
  • 多张发票必须写多行,一张发票一行
  • 每行 费用名称 固定为 招待费
  • 不写发票号汇总行
  • 不写本次总金额
  • 不写分类统计或金额累加

插入格式:

# 报销汇总

## YYYY-MM-DD 文件夹名称 招待费

| 日期 | 费用名称 | 发票号码 | 金额 | 餐厅/商户 | 来源文件 | 备注 |
|------|----------|----------|------|-----------|----------|------|
| YYYY-MM-DD | 招待费 | 1234567890 | ¥268 | 深圳市某某餐厅 | invoice1.pdf |  |
| YYYY-MM-DD | 招待费 | 9876543210 | ¥520.5 | 广州市某某酒楼 | invoice2.jpg |  |

(旧记录继续...)

12.4 注意事项

  • 每条记录之间保留一个空行(卡片末尾 ━━━━ 或表格后加一个空行再接下一条 ## 标题)
  • YYYY-MM-DD 使用当前扫描日期
  • 文件夹名称 使用被扫描的文件夹 basename
  • 最新的记录在最上面(按时间倒序排列)
  • 如果 summary_dir 目录不存在,输出警告并跳过
  • 操作完成后输出提示:📝 已追加摘要到 <summary_file 路径>

12.5 配置文件说明

  • config.json:用户的个人配置,包含真实路径,不应提交到版本库
  • config.json.sample:示例配置文件,供其他用户参考
  • .gitignore:排除 config.json,防止意外提交个人路径
Install via CLI
npx skills add https://github.com/wlzh/skills --skill wlzh-invoice-scanner
Repository Details
star Stars 572
call_split Forks 69
navigation Branch main
article Path SKILL.md
More from Creator