L’interface est localisée ; les présentations et documents des Skills sont traduits automatiquement par IA dans votre langue. Le code, les commandes, chemins et termes techniques restent en version originale, et le document de l’auteur fait foi.
Explorer les Skills
Productivité · SKILL.md

travel-expense-reimbursement-toolkit

travel-expense-reimbursement-toolkit

·--- name: 差旅费报销单生成 version: 1.2.2 description: 从行程截图(含Word文档内嵌截图)自动生成差旅费报销单(Word)和明细表(Excel),含凭证附件、页脚页码、费用结算 trigger: 差旅费报销、报销单、行程单、报销明细、生成报销单

Independent GitHub snapshot · Automated classification · Original documentation governs

Documentation de la Skill

GitHub

name: travel-expense-reimbursement-toolkit description: '·--- name: 差旅费报销单生成 version: 1.2.2 description: 从行程截图(含Word文档内嵌截图)自动生成差旅费报销单(Word)和明细表(Excel),含凭证附件、页脚页码、费用结算 trigger: 差旅费报销、报销单、行程单、报销明细、生成报销单'

·--- name: 差旅费报销单生成 version: 1.2.2 description: 从行程截图(含Word文档内嵌截图)自动生成差旅费报销单(Word)和明细表(Excel),含凭证附件、页脚页码、费用结算 trigger: 差旅费报销、报销单、行程单、报销明细、生成报销单

差旅费报销单生成技能

一、技能说明

本技能用于从用户提供的行程截图中,自动提取信息并生成差旅费报销单(Word .docx)和报销明细表(Excel .xlsx)。

用户只需提供:

  1. 行程截图(按案件分文件夹存放)——可以是独立图片文件,也可以是Word文档内嵌的截图
  2. 预支凭证截图(如有)
  3. 口头补充信息(如有)

Agent自动完成:

  • 扫描文件夹内所有资料(图片、Word文档、Excel等),不遗漏任何凭证来源
  • 如文件夹内含Word文档(.docx),自动提取内嵌截图并读取
  • 逐张读取截图,提取日期/时间/起点/终点/金额/车次
  • 同一案件多批次行程自动合并汇总(如1月出差+7月出差属同一案件,合并为一份报销单)
  • 按时间排序并编号
  • 生成Word报销单(明细表+预支凭证+原始凭证附件+页脚页码)
  • 生成Excel明细表(含费用结算区)
  • 文件名自动包含核心数据

二、铁律规则(必须严格遵守)

规则1:信息来源(最重要)

行程单的所有信息只能来源于:

  1. 截图(第一来源)- 直接从截图读取
  2. 用户对话(第二来源)- 用户明确告知的信息
  • 截图没有 + 对话没说 → 写"—"表示无
  • 绝对不允许自行推测或编造任何信息
  • 截图上有的信息优先归为"截图来源",即使对话中也提到了
  • 对话与截图信息不一致时,以截图为准,并提醒用户确认

规则2:逐张读取截图

收到截图后第一反应:

  1. 逐张仔细读取上面的所有信息(日期、时间、起点、终点、金额、车次)

  2. 每条信息标记来源(screenshot/dialog/inferred)

  3. 先读完所有截图,再开始整理数据

  4. 截图无时间 → 不要编,写"—"

  5. 同图多日期陷阱(极易犯错,必看):一张订单列表截图(如12306"待开票")常含多个"乘车日期"表头。每条订单必须对照它自身紧邻的日期表头填日期,绝对禁止用截图首日期套整图所有条目。录入后必须用 validate_data.py 的"按截图分组复核"逐图验证。

  6. 唯一要丢弃的时间:手机状态栏系统时间。完整手机截图最顶端的状态栏(有电池图标、信号格、运营商名称、WiFi图标),通常只显示时分(如"15:30")不显示日期,是截图时刻手机系统时间,与行程无关→丢弃。注意:不是每张截图都有状态栏(全屏/裁剪/APP隐藏时没有)。 除状态栏外,所有时间都保留——下单时间、购票时间、支付时间、乘车时间等,都是确定行程日期/时分的依据,绝不丢弃。 拿不准某个时间是不是状态栏时间时:不要擅自决定。两种处理方式:①向用户确认要不要去掉;②在文档末尾用红字标注该时间,问用户"此时间是否需要去掉"(参见规则4的"待确认问题清单"机制)。

  7. 不同平台时间表述不同,全部保留,优先用行程时间。不同平台对时间的标签不同,但不要因为标签是"下单/购票/支付"就丢弃——如果截图只有这个时间,它就是确定行程日期/时分的唯一依据。常见情况:

    • 12306高铁票:有"乘车日期"+"发车时间"→优先用;也有"下单时间"→备注保留
    • 滴滴/网约车:有"行程开始/出发时间"→优先用;只有"下单时间"→用下单时间确定日期和时分
    • 飞机票:有"起飞时间/出发日期"→优先用;只有"购票时间"→用购票时间确定日期
    • 支付宝/微信账单(顺风车/个人付款):只有"支付时间"→用支付时间(付款即乘车),收款方名称填入type或note
    • 原则:所有时间信息都保留不丢弃;优先取行程发生时间(乘车/出发/起飞);没有行程时间时用下单/购票/支付时间代替;唯一丢弃的是状态栏系统时间(见规则6)

规则3:排序规则

  • 添加新记录后立即按(date, time)排序并重新编号
  • 有时间的在前按时间排,无时间的排当天末尾
  • 同日多记录按地点首尾相连(行程连贯性)

规则4:异常发现与确认(必须主动做)

发现以下情况必须标记并向用户确认,绝不擅自处理:

  1. 同一时间同一车次多条记录 → 可能是改签
  2. 同一时间同一人在两个地方 → 逻辑不可能
  3. 金额异常(改签费但无对应票)→ 需确认改签逻辑
  4. 行程不连贯 → 需确认是否有遗漏
  5. 座席矛盾(同车次一等座+二等座)→ 改签特征

确认方式:

  • 备注栏用红字写明疑问
  • 文档末尾附"待确认问题清单"
  • 用户确认后删掉确认文字,生成最终版

规则5:图片处理

  • 不准拉伸图片:必须保持原图的宽高比
  • 直接从图片文件头读取实际尺寸(不依赖外部缓存)
  • 多订单截图如需裁剪:
    • 裁剪前用图像分析定位订单边界
    • 裁剪后逐张验证:内容完整 + 无残留其他订单信息

规则6:总额计算

  • 总额必须由程序自动计算(sum of items)
  • 不依赖手动填写的total字段
  • 生成文档后验证:sum(items) === case.total

规则7:文档结构

  • docx页脚:第 X 页 共 Y 页
  • 费用结算四项:预支/实际/补交/退还(不出现负数)
  • 文件名包含核心数据:预支X_实际Y_补交Z 或 退还Z
  • 附件顺序:一、明细表 → 二、预支凭证 → 三、原始凭证
  • 无预支时"二"写明"无预支凭证"

规则8:文件夹全量读取(核心原则,极易遗漏)

用户给了文件夹路径,就必须读取文件夹内的所有文件,不能只读独立图片。无论什么格式,都要打开看里面有没有截图或行程数据。

  1. 扫描全部文件,不挑格式:文件夹内可能有图片(.jpg/.png/.jpeg/.bmp/.gif/.webp)、文档(.docx/.doc/.wps/.pdf/.odt)、表格(.xlsx/.xls/.csv)、演示文稿(.pptx/.ppt)、压缩包(.zip/.rar/.7z)等。所有文件都要处理,不能只挑图片。
  2. 从文档中寻找截图:各种格式的文档里都可能内嵌了行程截图:
    • Word文档(.docx/.doc):内嵌图片在 word/media/ 下,用 extract_docx_images.py 提取
    • PDF文件(.pdf):可能含行程单截图,用PDF解析工具提取图片
    • Excel文件(.xlsx):可能含已整理的行程数据表,也可能插入了图片
    • WPS文档(.wps/.et/.dps):先转为对应微软格式再提取
    • 压缩包(.zip/.rar):先解压,再扫描解压出的文件
    • 其他格式:尝试用对应工具打开,寻找截图或行程数据
  3. 同时提取文档文字内容:文档中可能已有行程汇总表(日期/路线/金额),这些文字是可靠数据来源,应与截图交叉验证。
  4. 同一案件多批次合并:文件夹内不同日期的行程(如1月出差+7月出差)如果属于同一案件,必须合并为一份报销单,不能因为日期不同就判定"无关"而丢弃。
    • 判断标准:在同一案件文件夹内 = 同一案件 = 合并报销
    • 例外:用户明确说明某文件不属于本次报销范围
  5. 已有报销文档的处理:文件夹内可能已有之前整理好的报销文档(如"XX案差旅费报销,合计XXXX元.docx")。这些文档代表已整理但尚未报销的行程,应提取其内嵌图片和数据,与新截图合并汇总。

规则9:模型不支持图片时禁止编造(致命错误防范)

  1. 读取图片时如收到"当前模型不支持图片"或"内容已过滤"等提示:
    • 立即停止,不要继续编造数据
    • 第一时间告知用户:"当前模型无法读取图片,请切换到支持图片的多模态模型,或提供OCR方案"
    • 绝对禁止在无法读取图片的情况下自行编造车次、时间、金额等信息
  2. 这不是可选项:编造数据违反规则1(绝对不允许自行推测或编造任何信息),是最严重的错误。
  3. 替代方案(按优先级):
    • ① 切换到支持图片的多模态模型(推荐)
    • ② 使用OCR技能识别图片文字(如腾讯云OCR)
    • ③ 请用户口述截图内容
  4. Word文档中的文字内容不受此限制:即使模型不支持读图,docx中的文字(行程表、金额等)可以通过文本提取读取,是可靠数据来源。

三、数据结构

[
  {
    "case_short": "01_案件简称",
    "case_name": "案件全称",
    "items": [
      {
        "seq": 1,
        "date": "2026-05-05",
        "time": "07:15",
        "type": "高铁-二等座 G265",
        "from": "岳阳东",
        "to": "宁波",
        "amount": 649.00,
        "img": "docx_01.png",
        "note": "备注信息",
        "date_source": "screenshot"
      }
    ],
    "prepayment": {
      "amount": 5000.00,
      "date": "2026-01-01",
      "note": "当事人预支差旅费",
      "img": "prepayment.jpg"
    },
    "total": 0,
    "item_count": 0
  }
]

date_source字段

  • screenshot:信息直接从截图读取(正常黑色显示)
  • dialog:用户对话告知(红色字体+浅橙底色)
  • inferred:推测(红色字体+浅橙底色+"(推测)")
  • 不填:默认为截图来源

四、工作流程

步骤0:扫描文件夹全部文件(必做,不能跳过)

  1. 运行扫描脚本(自动列出所有文件并分类):
    python scan_folder.py "文件夹路径"
    
    脚本会自动:列出所有文件 → 按类型分类 → 提示哪些需要提取截图 → 自动对.docx调用extract_docx_images.py
  2. 如不使用脚本,手动检查:列出文件夹内所有文件(包括子文件夹),无论什么格式:
    • 图片文件(.jpg/.jpeg/.png/.bmp/.gif/.webp)→ 独立截图,直接读取
    • Word文档(.docx/.doc/.wps)→ 可能含内嵌截图,执行步骤0.5提取
    • PDF文件(.pdf)→ 可能含行程单截图,用PDF工具提取图片
    • Excel文件(.xlsx/.xls)→ 可能含已整理数据和插入图片
    • 演示文稿(.pptx/.ppt)→ 可能含截图
    • 压缩包(.zip/.rar/.7z)→ 先解压,再扫描
    • 其他文件 → 尝试打开,寻找截图或行程数据
  3. 判断是否有已整理但未报销的行程:如文件夹内已有报销文档(如"XX案差旅费报销,合计XXXX元.docx"),说明之前的行程已整理但未报销,需与新截图合并。
  4. 确认案件范围:同一文件夹 = 同一案件 = 合并报销。不同日期的行程只要在同一文件夹内,都属于同一案件。

步骤0.5:从文档中提取内嵌截图(如有非图片格式的文档文件)

  1. **Word文档(.docx)**最常见,运行提取脚本:
    python extract_docx_images.py "案件文档.docx" --output images/案件简称/docx_extracted/
    
  2. 其他格式文档也需提取内嵌图片:
    • PDF:用 pdfimages 或 Python PyMuPDF 提取图片
    • Excel:用 openpyxl 读取 xl/media/ 下的图片
    • WPS:先转为对应微软格式再提取
    • 或手动解压(docx/xlsx/pptx本质都是ZIP),图片在对应 media 目录下
  3. 同时提取文档文字内容(行程表、金额等),作为数据交叉验证来源
  4. 将提取的图片重命名为规范名称(如 docx_01_日期路线_车次.jpg),放入 images/案件简称/ 目录
  5. 解析图片与文字的对应关系:通过文档XML中的图片引用顺序,确定每张图片对应的行程

步骤1:收取截图

  1. 按案件分文件夹存放截图到 images/ 目录
  2. 收到截图后第一时间逐张读取所有信息
  3. 每条信息标记来源

步骤2:录入数据

  1. 将每条行程录入 expense_data.json
  2. 每条记录包含:seq, date, time, type, from, to, amount, img, note
  3. 添加新记录后立即按(date, time)排序并重新编号
  4. 录入完成后运行校验:python validate_data.py,特别关注"按截图分组复核"输出,逐图确认每条日期与截图日期表头一致(同图多日期时极易填错)

步骤3:异常检查

检查以下异常,发现后向用户确认:

  • 同一时间同一车次多条记录
  • 同一时间同一人在两个地方
  • 金额异常
  • 行程不连贯
  • 座席矛盾

步骤4:生成文档

# 安装依赖(首次使用)
npm install docx
pip install openpyxl Pillow

# 步骤0:扫描文件夹内所有文件(自动分类+提示哪些需要提取截图)
python scan_folder.py "文件夹路径"

# 步骤0.5:如文件夹内有Word文档,提取内嵌截图(scan_folder.py会自动调用,也可手动运行)
python extract_docx_images.py "案件文档.docx" --output images/案件简称/docx_extracted/

# 生成前先校验数据(推荐,可发现日期填错等问题)
python validate_data.py

# 生成Word文档
node generate_docs.js

# 生成Excel明细
python generate_excel.py

步骤5:验证

  1. 检查每个案件的total是否等于items求和(程序会自动校正)
  2. 检查图片是否拉伸(程序直接从文件头读取尺寸)
  3. 检查页脚是否有页码
  4. 检查文件名是否包含核心数据

五、费用结算逻辑

  • 有预支:
    • 实际 > 预支 → 需补交(差额)
    • 实际 < 预支 → 待退还(差额)
    • 实际 = 预支 → 两清
  • 无预支:
    • 需补交 = 实际金额
    • 待退还 = 0

六、文件命名规则

  • 有预支+补交:案件名报销单_预支X_实际Y_补交Z.docx
  • 有预支+退还:案件名报销单_预支X_实际Y_退还Z.docx
  • 无预支:案件名报销单_未预支_实际Y_补交Y.docx

七、历史错误反思(避免重犯)

错误0:发现异常不主动确认

同一时间同一车次出现两条记录(一等座+二等座),没有发现逻辑矛盾。改进:发现异常必须向用户确认。

错误1:编造时间数据

截图没读就编造时间。改进:收到截图第一反应逐张读取。

错误2:同日多订单时间互换

多订单截图时间对应错误。改进:逐个订单确认时间。

错误3:添加记录后未排序

序号与时间顺序不一致。改进:每次添加后立即排序+重新编号。

错误4:对话日期标成截图来源

截图上没有日期却标为screenshot。改进:逐条逐张判断来源。

错误5:对话与截图矛盾未发现

用户说9月30日,截图是10月30日。改进:以截图为准并提醒用户。

错误6:图片裁剪后未验证残留

裁剪后图片仍包含其他订单信息。改进:裁剪后逐张验证。

错误7:图片裁剪过度

裁剪掉了下单时间等重要信息。改进:裁剪前定位完整边界。

错误8:图片拉伸

不同案件同名图片尺寸混淆。改进:直接从文件头读取尺寸。

错误9:总额计算错误

手动算错总额。改进:程序自动求和+全量验证。

错误10:同图多日期误套首日期

一张12306截图含两个乘车日期(顶部02-03 + 底部02-01),转录时把同图所有条目都套用了首日期02-03,导致02-01的订单日期填错。改进:每条订单对照自身紧邻的"乘车日期"表头填日期,录入后用 validate_data.py 的"按截图分组复核"逐图验证。

错误11:忽略文件夹内文档,未合并多批次行程

真实案例:用户给了文件夹路径,里面有3张7月截图 + 1个Word文档(含1-2月6条行程截图)。Agent只整理了3张独立截图,把Word文档判定为"无关文件"丢弃。实际上Word文档内的行程是已整理但未报销的,应与7月新行程合并为一份报销单(9条行程,¥5071.03)。 根因:把"日期不同"等同于"案件不同",且只读图片不读文档,缺乏"同一文件夹=同一案件=合并报销"的意识。 改进:

  • 收到文件夹路径后,必须扫描全部文件,无论什么格式(规则8)
  • 文档内的截图必须提取(步骤0.5),不只是.docx,所有格式都要处理
  • 同一文件夹内不同日期的行程必须合并汇总
  • 新增规则8"文件夹全量读取"

错误12:模型不支持图片时编造数据

真实案例:模型不支持图片读取(系统返回"内容已过滤"),但Agent没有告知用户,而是自行编造了车次号、发车时间、金额等具体数据,生成了看似完整实则全部虚构的报销单。这直接违反了规则1"绝对不允许自行推测或编造任何信息"。 根因:收到"不支持图片"提示后未停止,而是选择编造数据来"完成任务"。 改进:

  • 收到"不支持图片"提示后必须立即停止,告知用户切换模型
  • 绝对禁止在无法读取图片时编造任何数据
  • 新增规则9"模型不支持图片时禁止编造"
  • Word文档中的文字内容不受此限制,可通过文本提取读取

八、技术要点

docx-js 9.x API

  • 页脚必须用 footers: { default: docFooter },不是 footer: docFooter
  • Footer中用 PageNumber.CURRENT 和 PageNumber.TOTAL_PAGES 显示页码
  • 图片用 ImageRun + transformation: { width, height },尺寸按原始比例计算

图片尺寸读取

直接从文件头读取,不依赖外部缓存:

  • PNG:IHDR偏移16-23
  • JPEG:扫描SOF标记(0xFFC0-0xFFCF)
  • BMP:偏移18-22
  • GIF:偏移6-8

总额自动校正

generate_docs.js 和 generate_excel.py 启动时:

const actualTotal = Math.round(items.reduce((s, it) => s + it.amount, 0) * 100) / 100;
if (caseData.total !== actualTotal) {
  caseData.total = actualTotal; // 自动校正
}
Skills enregistrées