SSkilltecabyclaudinhocode
Enviar skill
← Voltar para o catálogo

yss-overtime-submission

DevOps e Infra

自动计算和提交赢时胜(YSS)公司的加班单(奋斗单)。当用户提到"提加班单"、"提奋斗单"、"算加班时长"、"SHR 加班"、"我要奋斗"、"禅道考勤"、"补提加班"、"这周加班还没提"等场景时,必须使用本 skill。会从禅道 OA 考勤数据自动抓取打卡记录,结合中国大陆法定节假日和调休补班(chinese_calendar 库)正确判断工作日类型,按公司规则(工作日 19 点后 / 节假日打卡到打卡 + 午晚餐扣除)计算应报时长,与 SHR 已提交奋斗单做差集,从禅道工时确认拉取奋斗内容候选,生成待提交清单后通过 Playwright 半自动提交到金蝶 s-HR Cloud。

3estrelas
Ver no GitHub ↗Autor: jiya1996Licença: MIT

赢时胜加班单提交助手

创建人:jiya1996 最后实测验证:2026-05-12 版本:2.1(补充单日超过 8h 的按开始时间拆分 + 分批提交)

分发给同事使用:见 references/installation_for_colleagues.md 本 skill 遵循 agentskills.io 开放标准,可装在 Claude Code / OpenClaw / Cursor / Goose 等 30+ 兼容客户端里。

这个 skill 解决什么问题

赢时胜员工每周需要把加班时长提交到 SHR 系统(金蝶 s-HR Cloud)的「我要奋斗」模块。整个流程涉及:

  1. 禅道(pm.example.com:8071)拉打卡数据
  2. 公司规则算出每天该报多少加班时长
  3. SHR(oa.example.com:5887)查已提交的奋斗单做差集
  4. 从禅道工时确认页拉当天做的事(用作奋斗内容)
  5. 在 SHR「多条创建」里逐条填表 + 提交

整个流程做成「人在环(HITL)的半自动化」:计算和填表自动化,提交前用户人工 review。

何时使用本 skill

触发条件(任一即可):

  • 用户提到"提加班单"、"提奋斗单"、"算加班"、"我要奋斗"
  • 用户问"这周加班几小时"、"还有哪几天没提加班"
  • 用户提到 SHR / 金蝶 / <your-company> 加班相关
  • 用户说"帮我把上周加班补一下"

⚠️ 必读前置警告

1. 节假日库每年要更新一次

本 skill 用 chinese-calendar 库识别中国大陆法定节假日 + 调休补班。该库每年初待国务院公布次年放假安排后由维护者更新。

每年元旦后第一次跑 skill 前,运行

python -m pip install -U chinese-calendar

否则跨年的日期判断会回落到「周一~周五 = 工作日」简单逻辑,调休补班和法定假日全算错scripts/holidays.py 里已经做了 NotImplementedError 兜底 + warning,但你不会想要那个。

2. 公司可能禁用 RPA

金蝶 s-HR 可能埋点检测自动化操作。本次(2026-05-08)实测可用,不代表长期安全。用前最好和 IT/HR 确认一句——哪怕用自己账号操作。

3. Windows 控制台编码

Windows cmd / git-bash 默认 cp936,撞中文 + emoji 必崩。所有 Python 脚本必须加:

PYTHONIOENCODING=utf-8 python ...

4. 永远不要全自动提交

submit_overtime.py 必须传 --confirm 才会真正点提交按钮。orchestrator.py 走完所有阶段会暂停问 yes 才提交。

整体架构

┌────────────────────────────────────────────────────┐
│ 用户保持登录的 Chrome(手动过验证码 + 记密码)        │
│   (启动方式见 references/chrome_setup.md)          │
│   ├─ 禅道 tab    https://pm.example.com:8071       │
│   └─ SHR  tab    https://oa.example.com:5887       │
└─────────────────────┬──────────────────────────────┘
                      │ Chrome DevTools Protocol (CDP, port 9222)
                      ▼
┌────────────────────────────────────────────────────┐
│ Playwright(connect_over_cdp,复用登录态)          │
│   ├─ 抓禅道考勤打卡 (extract_attendance.py)         │
│   ├─ 抓 SHR 已提交奋斗单 (extract_submitted.py)     │
│   ├─ 抓禅道工时确认(奋斗内容)(extract_effort.py)   │
│   └─ 多条创建网格填表 + 提交 (submit_overtime.py)    │
└─────────────────────┬──────────────────────────────┘
                      │
                      ▼
┌────────────────────────────────────────────────────┐
│ 计算 + 节假日识别                                    │
│   ├─ calculator.py:工作日/非工作日规则、向下取整    │
│   └─ holidays.py:chinese_calendar 调休补班识别     │
└────────────────────────────────────────────────────┘

SHR 的三个关键 URL(金蝶 s-HR 是 SPA,每个页面 uipk 不一样):

  • 默认入口:uipk=...AtsOverTimeBillForm空白单条新建表单(干扰页)
  • 列表页:uipk=...AtsOverTimeBillList抓已提交清单 + 入口枢纽
  • 多条创建:uipk=...AtsOverTimeBillForm.PersonnalBatch&method=addNew真正提交的网格

标准使用流程

阶段 0:一次性环境准备

  1. references/chrome_setup.md 启动带 --remote-debugging-port=9222 的 Chrome
  2. 安装依赖:
    python -m pip install -r requirements.txt
    python -m playwright install chromium
    
  3. 在 Chrome 里手动登录禅道 + SHR(过验证码、勾「记住密码」)
  4. 自检:日常浏览器访问 http://localhost:9222,能看到禅道和 SHR 两个 tab

阶段 1:算时长 + 查差集(dry-run)

PYTHONIOENCODING=utf-8 python scripts/orchestrator.py \
    --start 2026-05-04 --end 2026-05-10 \
    --content "<你这周加班期间做的事>" \
    --dry-run-only

orchestrator 会:

  1. 抓禅道考勤打卡
  2. 抓 SHR 已提交奋斗单
  3. 计算应提交差集;单日超过 8h 时自动按开始时间拆分多条(如 09:44-18:44 8h + 18:45-21:45 3h)
  4. 填奋斗内容(优先级--content 命令行 > 用户终端输入 > 禅道工时确认页拉建议)
  5. 把待提交清单存到 plan.json,dry-run 输出后退出

奋斗内容来源策略(无默认占位,必须三选一拿到,否则报错退出):

  • 跑命令时加 --content "..." 一次性给所有单子填同样内容
  • 不加 --content 时,会对每条单子先尝试从禅道工时确认页拉当天的任务名作为建议
  • 禅道工时为空 → 终端会要求你手输(必填)

输出格式(示例):

=== DRY RUN:以下 N 条**不会**真实提交 ===
  • 2026-MM-DD 周X  HH:MM-HH:MM  报 X.Xh  [工作日/非工作日]  使用方式=...  分段=1/2  提交时段=HH:MM-HH:MM  | <奋斗内容>

阶段 2:确认无误后真正提交

PYTHONIOENCODING=utf-8 python scripts/submit_overtime.py \
    --plan plan.json --confirm

或一键:

PYTHONIOENCODING=utf-8 python scripts/orchestrator.py \
    --start 2026-05-04 --end 2026-05-10 \
    --content "<填你这周加班做的事>" --confirm

提交流程:

  1. goto SHR_BILL_MULTI_CREATE_URL 直达多条创建网格
  2. 对每条单子:点 #addRow_entries → 填日期 → 等金蝶自动带类型/开始时间/使用方式 → 选积分下拉 → 填备注
    • 若该日总时长超过 8h,脚本会把同一天拆成多条,并覆盖 SHR 自动带出的奋斗开始/结束时间、休息时长和隐藏申请时长缓存。
    • 后续分段的开始时间必须和前一段不同(小时、分钟都建议错开 1 分钟),否则 SHR 会报「奋斗时间不能超过8个小时」。
  3. 点顶部 #submit 按钮 → 弹金蝶 messenger 确认 → 点「确认」 a 标签
  4. URL 跳到 AtsOverTimeBillList = 提交成功

成功后到 SHR 列表页二次核对。

计算规则速查

详见 references/calculation_rules.md

工作日(含调休补班)

  • 仅可申请奋斗积分
  • 加班 = 下班打卡 − 19:00
  • 必须 ≥ 1h 才能提交(exact 1h 可以提)
  • 向下取整到 0.5h

非工作日(含法定假日)

  • 默认调休(可改奋斗积分)
  • 加班 = 下班打卡 − 上班打卡 − 午晚餐扣除
  • 午餐扣除:上班打卡 < 12:00 时扣 1h
  • 晚餐扣除:下班打卡 ≥ 19:00 时扣 1h
  • 单日净时长 > 8h:自动拆分多条,默认第一条最多 8h,第二条从上一条结束后 1 分钟开始

文件结构

yss-overtime-submission/
├── SKILL.md                           # 本文件
├── requirements.txt                   # playwright + chinese-calendar
├── references/
│   ├── calculation_rules.md           # 计算规则全集
│   ├── chrome_setup.md                # 启动 Chrome debug 模式
│   └── system_navigation.md           # 禅道 / SHR 真实 URL + selector 对照表
└── scripts/
    ├── calculator.py                  # 纯计算逻辑(带 doctest)
    ├── holidays.py                    # chinese_calendar 包装 + 调休补班识别
    ├── selectors.py                   # 集中管理 CSS selectors(UI 改版改这里)
    ├── connect_chrome.py              # Playwright CDP 连接工具
    ├── extract_attendance.py          # 抓禅道打卡
    ├── extract_submitted.py           # 抓 SHR 已提交单
    ├── extract_effort.py              # 抓禅道工时确认(奋斗内容候选)
    ├── submit_overtime.py             # 提交加班单(dry-run / confirm)
    ├── orchestrator.py                # 总入口
    ├── simulate.py                    # 不连浏览器的逻辑模拟(mock 数据)
    └── debug/                         # selector 漂移时复用的 dump 脚本
        ├── debug_shr.py               # 列表页 dump
        ├── debug_shr_list.py          # 点奋斗列表按钮 + dump
        ├── debug_shr_filter.py        # 展开筛选 + dump 日期 input
        ├── debug_shr_query.py         # 查询 + dump 表格行
        ├── debug_shr_multi_create.py  # dump 多条创建网格
        ├── debug_zt_effort.py         # dump 禅道工时确认页
        └── debug_zt_effort_5_6.py     # 拉某天工时(输出 demo)

Selector 失效时的修复流程

UI 改版让脚本失效是迟早的事。修复步骤:

  1. 在 debug Chrome 里访问出问题的页面
  2. scripts/debug/ 里对应的 dump 脚本(5 个 dump 脚本对应 5 个关键页面)
  3. 比对输出,定位错位的 selector
  4. scripts/selectors.py 里对应的常量
  5. python scripts/orchestrator.py --start ... --end ... --dry-run-only 自测

所有 selector 集中在 scripts/selectors.py——一处出错只改一处。

已知坑(实跑踩过)

解决
goto AtsOverTimeBillForm 直接进了一个空白表单干扰页,不是奋斗列表AtsOverTimeBillList 直达列表页
列表页默认收起筛选,要先点「展开筛选」按钮才有日期 input脚本里先 get_by_text("展开筛选").click()
顶部「奋斗列表」按钮 #returnToOverTimeBillListnot visible(被父容器遮住),普通 click 失效page.evaluate("...click()") JS 兜底
列表页的「查询」按钮用 get_by_text("查询") 会误匹配到「未查询到结果」div#filter-search
多条创建网格的 cell selector 不是 data-field,是 jqGrid 的 aria-describedby="entries_*"td[aria-describedby="entries_otDate"]
提交后弹的不是 native dialog,是金蝶 messenger 容器(page.on("dialog") 抓不到)[class*="messenger"] 里的「确认」 a 标签 click
禅道工时页的「名称」「描述」是 <input value="..."> 不是 td 文本td.querySelector('input').value
禅道工时 URL 不是 m=effort&f=mywork,是 m=todo&f=confirmuserconsumed已修正 selectors.py
单日加班超过 8h 时,同一张单里第二条如果沿用 SHR 自动带出的同一开始时间,会报「奋斗时间不能超过8个小时」按起始时间拆分多条,第二段从上一段结束后 1 分钟开始,并同步更新 jqGrid data / row currentData / storeValue 三处缓存

Como adicionar

/plugin marketplace add jiya1996/yss-overtime-submission

O comando exato pode variar conforme o repositório. Confira o README no GitHub.

Comentários · Nenhum comentário

Entre para comentar. Entrar

  • Ainda não há comentários. Seja o primeiro.