技能包:
umanage-batch-ops
适用:<租户>.changyan.com系智慧教务平台(学生 / 班级 / 教师 / 任课四大模块)
体量:6 个文件、26 KB,19 条子命令
依赖:Node ≥ 22 + 一个开着远程调试端口的 Chrome,不需要 playwright / puppeteer
下载:https://7998888.xyz/wp-content/uploads/2026/10/umanage-batch-ops.zip
为什么要做成 Skill
上一篇记了这套教务系统批量维护的踩坑过程。但「记录」和「能复用」是两回事:上一次做完,
下次换一所学校、换一个学年,还是得从「怎么让 Chrome 被程序驱动」重新开始爬一遍。
所以这次把它整个收敛成一个技能包:接口、脚本、判定规则、验证规范,全部固化下来,
下次只需要换一个 config.json。
判断标准很简单——如果一套流程的知识密度高到「不看笔记做不出来」,它就值得做成 Skill。
教务系统恰好符合:接口有 10 个,坑有 12 个,而且每个坑都是静默失败,不报错、不抛异常,
只是数据没落库。
技能包长什么样
umanage-batch-ops/
├── SKILL.md # 工作流 + 铁律 + 坑位清单(给 AI 看的说明书)
├── references/
│ ├── api.md # 10 个接口的完整字段、参数位置、返回结构
│ └── chrome-cdp-setup.md # 让 Chrome 能被驱动的那 5 个坑
└── scripts/
├── umanage.mjs # 主 CLI,19 条子命令
├── parse-xls.mjs # 不装库解析老式 .xls(OLE2 + BIFF8)
└── config.example.json # 配置模板
三个文件的分工是刻意分开的:
- SKILL.md 回答「该怎么做」,是决策层
- references/ 回答「为什么是这样」,是事实层,只在需要时读,不占上下文
- scripts/ 回答「具体怎么敲」,是执行层,可独立运行
三条铁律
这三条不是风格偏好,是这次踩出来的血泪:
- 先 dry-run,再
--execute。 所有写操作脚本默认只读,必须显式带--execute才落库。 - 状态码不算成功。
{"status":1,"msg":"success"}只代表请求被受理。
实测批量删 34 个班,接口返回status=1,实际有 1 个班因为「班级下存在用户」没删掉。 - 删除前先备份。 学生删除会连同账号一起清掉,先落一份
{id, userName, loginName}快照再动手。
limit 超了也不报错——全都表现为「返回 200,但数据没变」。所以「复验」不是可选项,是流程的一部分。
六条工作流
整个技能包对外就 19 条子命令,按场景分成六条流水线:
| # | 工作流 | 关键命令 |
|---|---|---|
| 1 | 批量删除某年级学生 | students-delete <年级> --execute |
| 2 | 批量删除某年级班级 | classes-delete <年级> --execute |
| 3 | 解绑任课教师(删班前置) | unbind <年级> --execute |
| 4 | 批量导入学生名单 | students-add <年级> --file plan.json --execute |
| 5 | 教师建号与重名清理 | teacher-add / dedupe |
| 6 | 任课表格红黄提取与落库核对 | grid / actual / compare |
举两个例子。
批量导入学生——输入一个 {"高二1班":["张三","李四"]} 的 JSON,脚本会先读该班现有名单、
按重数扣除已存在的同名,所以重复执行是安全的:
node umanage.mjs students-add 高二 --file plan.json --execute
任课表格核对——这是最实用的一条。设置教师时表格里会标红标黄,处理完名册后要知道
「到底有没有真的存进去」,靠眼睛看表格是不行的(表格有缓存):
node umanage.mjs grid 高二 > grid.json # 提取 Handsontable 网格 + 红黄标注
node umanage.mjs actual 高二 > actual.json # 抓各班真实任课配置
node umanage.mjs compare grid.json actual.json
红底 =
用户[xxx]不存在(教师库没这个账号);黄底 =
用户[xxx]存在同名用户(教师库有重名,打名字区分不了)。而且它是打开表格那一刻的快照,接口不实时校验——改完名册必须关掉弹窗重开才看得到效果。
十二个坑里最值钱的六个
| 坑 | 现象 | 规避 |
|---|---|---|
limit 超过 50 |
静默返回整页 HTML,不报错 | 分页 + startsWith('<') 探测 + 退避重试 |
缺 X-Requested-With |
同上,返回整页 HTML | 批量类接口一律带上 |
| token 位置 | 多数接口放 body,/teaching/batch-* 必须放 URL 查询串 |
按接口分别处理 |
| 建教师「假成功」 | 返回 新增成功,但根本没落库 |
5 个可空字段(idCardNo 等)即使为空也必须带 |
| 名册缓存延迟 | 删完立刻查还是旧数据,误判成失败 | 等几十秒再复验 |
| 名册翻页漏记录 | 按页翻总数会漏人 | 查重名一律用 userLoginName=<姓名> 精确搜 |
还有一条是平台能力的:前端 RSA 加密是确定性的(PKCS#1 v1.5 填充),
同一明文每次密文相同。所以密码密文抓一次就能长期复用,不需要每次重新加密。
// 在页面控制台里取一次即可
window.encryptedString('laoshi12')
验证规范
批量操作的收尾必须是这四步,缺一步都不算完成:
- 接口复验——重拉目标列表,确认数量与内容
- 逐项复验——批量操作要打印每个子项结果,不能只看汇总
- 页面复验——刷新页面截图留证(树节点人数、空态文案)
- 备份落地——删除类操作必须留 JSON/CSV 快照,含 id 与关键字段
这次就是靠第 1 条抓出一个漏网之鱼:高二某个班整行 7 格任课配置提交时被漏掉了,
表格上看不出来,接口一比对就现形了。
怎么装
解压后放进 WorkBuddy 的技能目录即可:
unzip umanage-batch-ops.zip -d ~/.workbuddy/skills/
cd ~/.workbuddy/skills/umanage-batch-ops/scripts
cp config.example.json config.json # 填 token / schoolId / campusId / teachingCycleId
node umanage.mjs help # 看全部子命令
config.json 里的值全部来自浏览器:
token 在地址栏 ?IFLYTEK_CSRFTOKEN= 后面,
schoolId / campusId / teachingCycleId 在 F12 → Network 任意一个列表请求的 query 里。
边界
这个包只操作调用方自己有权管理的租户。凭据一律放 config.json,不要写进脚本或提交到仓库;
对外分享时学校名、账号、token、师生姓名都已脱敏。
批量删除不可逆,执行前应该先列清影响范围再确认。
技能包本身不含任何后门、不上报数据、不联外网——它只通过 CDP 驱动你自己机器上的浏览器,
所有请求都由你的浏览器带着你已有的登录态发出。







暂无评论内容