安装与下载
1 ClawHub CLI
从源直接安装技能的最快方式。
npx clawhub@latest install zhongshan-lesson-plan
2 手动安装
将技能文件夹复制到以下位置之一
~/.openclaw/skills/
{'/skills/'}
优先级:工作区 › 全局 › 内置
3 提示词安装
将此提示词复制到 Openclaw 即可自动安装。
请帮我使用 Clawhub 安装 skill-zhongshan-lesson-plan。如果尚未安装 Clawhub,请先安装(npm i -g clawhub)。
更倾向于下载?
获取包含原生技能文件的ZIP压缩包。
基本信息
zhongshan-lesson-plan
安装指南
- ClawHub CLI
从源直接安装技能的最快方式。
npx clawhub@latest install zhongshan-lesson-plan - 手动安装
将技能文件夹复制到以下位置之一
全局模式
~/.openclaw/skills/
工作区
/skills/
优先级:工作区 > 本地 > 内置 - 提示词安装
将此提示词复制到 OpenClaw 即可自动安装。
请帮我使用 Clawhub 安装 zhongshan-lesson-plan。如果尚未安装 Clawhub,请先安装(npm i -g clawhub)。
更倾向于下载?
获取包含原生技能文件的ZIP压缩包。
下载技能 (.zip)
什么是
此 Openclaw Skills 工作流会分析职业教育教案模板,根据课程主题推断课程名称,生成结构化教学内容,并将结果写入原始 DOCX 文件。它支持教师、班级、教材、主题和课时等详细信息;如果缺少可选信息,则使用合理的默认值。
该技能专为包含合并单元格和多分区教学表格的模板而设计。它不使用 python-docx,而是通过 zipfile 和 lxml 编辑底层 Word XML,从而保留纵向合并、网格跨列、标签、字体、对齐方式和版式。
应用场景
根据 DOCX 模板、主题和课时数生成完整的职业学校教案。
填写教师、班级、教材、课程名称和教学内容等教案元数据。
创建知识、能力、素质、思政教育、教学重点、教学方法、作业、评价和反思等部分。
为电子、编程、嵌入式系统、PLC、网络、AI、数据库及相关技术学科编写教师活动和学生活动内容。
保留包含纵向合并、横向跨列和受保护标签单元格的复杂 Word 表格。
在保留源模板视觉结构的同时,批量或重复生成标准化教案。
工作原理
接收 DOCX 模板、课程主题和课时数,以及可选的教师、班级和教材信息。
从 DOCX ZIP 软件包中提取 word/document.xml,并检查表格结构,包括行、单元格、gridSpan 值和 vMerge 属性。
将 15 行模板映射到对应的语义字段,使用从零开始的行和单元格索引确保准确定位。
根据课程映射规则,将 MOSFET、C 语言、PLC、STM32、PCB、数据库、TCP/IP 或人工智能等主题关键词与课程进行匹配,从而推断课程名称。
生成涵盖课程导入、知识讲授、原理分析、演示、练习、复习和作业的教学内容。
使用 lxml 创建格式化的 Word 段落,包括宋体、10.5 磅字号、间距、对齐方式和多段落支持。
仅移除目标单元格中的现有内容,保留标签单元格和表格属性,并将生成的内容直接插入 XML 树。
将修改后的 document.xml 与原始 DOCX 资源重新打包,生成新的输出文件。
交付前通过检查行数、单元格数量、vMerge 连续性及其他结构要求来验证生成的文档。
配置指南
使用兼容的 Python 3 环境,并保持原始职业教案 DOCX 模板不变。
安装 XML 处理依赖项:
python3 -m pip install lxml
写入内容之前检查模板的 XML:
python3 -c "import zipfile; p = '中专教案模板.docx'; z = zipfile.ZipFile(p); print(z.read('word/document.xml').decode('utf-8'))"
确认模板符合预期的 15 行结构,然后在 XML 写入脚本中配置源文件和输出路径。使用 zipfile 读取和重写 DOCX 软件包,并使用 lxml.etree 修改 word/document.xml。
提供必需输入:DOCX 模板、课程主题和课时数。教师、班级和教材为可选项;否则使用文档规定的默认值:刘老师、22 级电子信息 1 班,以及《模拟电子技术基础》第 5 版。
写入内容时不要使用 python-docx。它可能会重新生成 XML 并破坏基于 vMerge 的纵向单元格合并。
生成后运行结构验证,并在 Microsoft Word 或兼容编辑器中打开输出 DOCX 进行视觉检查。
数据架构
此技能将 DOCX 视为包含 WordprocessingML XML 的 ZIP 软件包。主要编辑的文件是 word/document.xml;其他所有软件包文件均保持原样复制。
区域 XML 位置或索引 用途
基本信息 行 0-3 教师、课程名称、教材、班级、教学内容和课时
学习目标 行 4-6 知识、能力和素质目标;第一列使用 vMerge
思政与教学规划 行 7-9 思政要素、教学重点与难点、教与学的方法
教学过程 行 10-12 分区标题、三列表头,以及教学内容、教师活动和学生活动
评价与反思 行 13-14 作业、评价方式、教学反思和改进建议
重要字段映射使用从零开始的 (row, cell) 坐标,包括教师内容 (0, 1)、课程内容 (0, 3)、教材 (1, 1)、班级 (2, 1)、教学内容 (3, 1)、课时 (3, 3)、目标 (4, 2) 至 (6, 2)、教学过程 (12, 0) 至 (12, 2),以及反思 (14, 1)。
生成的长文本字段可表示为段落字符串列表。空字符串会创建段落分隔。现有标签单元格必须保持不变。格式设置使用宋体、XML 字号 sz=21(即 10.5 磅)、内容左对齐、表头居中对齐,并保留 gridSpan 和 vMerge 属性。
高级特性
直接编辑 WordprocessingML,避免使用 python-docx 重建文档,并保护纵向合并单元格。
自动推断课程名称,将技术关键词映射到模拟电子、微控制器、C 语言、数字电子、传感器、自动控制、PLC、嵌入式系统、IoT、AI、数据库和计算机网络等学科。
默认值处理功能可在未提供教师、班级或教材元数据时生成内容。
支持在单元格中插入多段落内容,用于结构化目标、活动、作业、评价和反思。
根据模板映射单元格,将可编辑内容单元格与固定标签单元格区分开来。
XML 层级验证会检查预期的 15 行结构、每行单元格数量,以及 vMerge 的重新开始和延续标记。
工作流保留原始 DOCX 软件包资源,只替换
word/document.xml
。
通过扩展主题关键词到课程的查找表,即可添加新的学科映射,使 Openclaw Skills 工作流适用于更多课程体系。
name: zhongshan-lesson-plan description: 中专教案模板填充——分析docx模板表格结构,生成教案内容,用直接XML操作填充模板文件 category: productivity 中专教案模板填充技能
基于中专教案模板(.docx),自动生成并填写教案内容。
触发条件
用户提供 docx 模板文件 + 教案主题 + 课时数,要求填表生成教案。
可选参数: 授课教师、授课班级、授课教材。缺失时按默认规则填充。
默认填充规则
字段 默认值 说明
授课教师 刘某某 用户未提供时自动填充
课程名称 根据教案主题推断 从主题关键词匹配课程名,见下方映射表
授课班级 22级电子信息1班 用户未提供时的默认班级
授课教材 《模拟电子技术基础》(第5版) 默认教材
技术原理
核心挑战: Microsoft Word .docx 文件使用 XML 格式存储内容,其中表格的纵向合并单元格(vMerge)是一个特殊属性。python-docx 库在读写时会破坏 vMerge 属性,导致合并单元格变成独立单元格。
解决方案: 使用 zipfile + lxml 直接操作 .docx 文件的 XML 底层结构,完全绕过 python-docx,确保 vMerge 和其他表格格式零损坏。
工作流程
第一步:分析模板结构
在编写教案内容之前,必须先分析模板的表格结构。
# 从docx中提取document.xml
python3 -c "
import zipfile
docx_path = r'模板文件路径'
with zipfile.ZipFile(docx_path) as z:
with z.open('word/document.xml') as f:
print(f.read().decode('utf-8'))
"
然后检查 document.xml 中的 部分,统计每一行()的单元格数、gridSpan 和 vMerge 属性。
第二步:中专教案模板结构详解
模板:中专教案模板.docx
XML行索引 原始行号 字段 单元格数 说明 0 R1 授课教师/课程名称 4 ci1内容区gridSpan=2, ci3内容区gridSpan=6 1 R2 授课教材 2 ci1内容区gridSpan=9 2 R3 授课班级 2 ci1内容区gridSpan=9 3 R4 授课内容/授课时长 4 ci1内容区gridSpan=7, ci3=授课时长标签, ci4空 4 R5 教学目标+知识目标 3 ci0 vMerge=restart, ci1标签, ci2内容区gridSpan=8 5 R6 (vMerge续)+能力目标 3 ci0 vMerge, ci1标签, ci2内容区gridSpan=8 6 R7 (vMerge续)+素质目标 3 ci0 vMerge, ci1标签, ci2内容区gridSpan=8 7 R8 思政元素 2 ci0标签, ci1内容区gridSpan=9 8 R9 教学重点与难点 2 ci0标签, ci1内容区gridSpan=9 9 R10 教法和学法 2 ci0标签, ci1内容区gridSpan=9 10 R11 教学过程(标题) 1 全行合并gridSpan=10 11 R12 三列表头 3 ci0(6列), ci1(3列), ci2(1列) 12 R13 主教学内容区 3 ci0=教学环节内容, ci1=教师活动, ci2=学生活动 13 R14 课后作业/评价方式 4 ci0标签, ci1内容区gridSpan=4, ci2标签gridSpan=2, ci3内容区gridSpan=3 14 R15 教学反思与改进建议 2 ci0标签, ci1内容区gridSpan=9
总行数:15行
第三步:使用直接XML操作填充内容
完整代码模板:
import zipfile
import os
from lxml import etree
# ===== 配置 =====
src = r'模板文件路径' # 原始模板
out = r'输出文件路径' # 生成的教案
W = '{http://schemas.openxmlformats.org/wordprocessingml/2006/main}'
# ===== 读入XML =====
with zipfile.ZipFile(src, 'r') as zin:
doc_xml = zin.read('word/document.xml')
root = etree.fromstring(doc_xml)
# 找到表格
body = root.find(W + 'body')
tbl = body.find(W + 'tbl')
rows = tbl.findall(W + 'tr')
# ===== 创建格式化段落 =====
def make_paragraph(text, alignment='left'):
"""创建带格式的段落元素"""
p = etree.SubElement(etree.Element('dummy'), W + 'p')
pPr = etree.SubElement(p, W + 'pPr')
# 对齐方式
jc = etree.SubElement(pPr, W + 'jc')
jc.set(W + 'val', alignment)
# 行间距
sp = etree.SubElement(pPr, W + 'spacing')
sp.set(W + 'before', '20')
sp.set(W + 'after', '20')
sp.set(W + 'line', '320')
sp.set(W + 'lineRule', 'auto')
# 运行(Run)
r = etree.SubElement(p, W + 'r')
rPr = etree.SubElement(r, W + 'rPr')
# 字体设置
rf = etree.SubElement(rPr, W + 'rFonts')
rf.set(W + 'ascii', '宋体')
rf.set(W + 'hAnsi', '宋体')
rf.set(W + 'eastAsia', '宋体')
# 字号(21 = 10.5pt)
sz = etree.SubElement(rPr, W + 'sz')
sz.set(W + 'val', '21')
szCs = etree.SubElement(rPr, W + 'szCs')
szCs.set(W + 'val', '21')
# 文本内容
t = etree.SubElement(r, W + 't')
t.text = text
t.set('{http://www.w3.org/XML/1998/namespace}space', 'preserve')
return p
# ===== 填充单元格内容 =====
# 清除单元格中的所有段落
cell = rows[row_index].findall(W + 'tc')[cell_index]
for p in cell.findall(W + 'p'):
cell.remove(p)
# 写入新内容(支持多段落)
if isinstance(content, str):
if content.strip():
cell.append(make_paragraph(content))
else:
for line in content:
if line.strip():
cell.append(make_paragraph(line))
# ===== 写回文件 =====
new_doc_xml = etree.tostring(root, xml_declaration=True, encoding='UTF-8', standalone=True)
if os.path.exists(out):
os.remove(out)
with zipfile.ZipFile(src, 'r') as zin:
with zipfile.ZipFile(out, 'w', zipfile.ZIP_DEFLATED) as zout:
for item in zin.infolist():
if item.filename == 'word/document.xml':
zout.writestr(item, new_doc_xml)
else:
zout.writestr(item, zin.read(item.filename))
print(f'✅ 教案已生成: {out}')
第四步:验证
填写完成后必须验证以下项:
W = '{http://schemas.openxmlformats.org/wordprocessingml/2006/main}'
with zipfile.ZipFile(output_path, 'r') as z:
doc_xml = z.read('word/document.xml')
root = etree.fromstring(doc_xml)
rows = root.findall('.//' + W + 'tr')
# 1. 行数检查
assert len(rows) == 15, f"行数错误: 期望15, 实际{len(rows)}"
# 2. 每行单元格数检查
expected_cells = [4, 2, 2, 4, 3, 3, 3, 2, 2, 2, 1, 3, 3, 4, 2]
for i, row in enumerate(rows):
cells = row.findall(W + 'tc')
assert len(cells) == expected_cells[i], \
f"R{i+1} 单元格数错误: 期望{expected_cells[i]}, 实际{len(cells)}"
# 3. vMerge检查
r5_vm = rows[4].findall(W + 'tc')[0].find(W + 'tcPr').find(W + 'vMerge')
assert r5_vm is not None and r5_vm.get(W + 'val') == 'restart', "R5 vMerge错误"
r6_vm = rows[5].findall(W + 'tc')[0].find(W + 'tcPr').find(W + 'vMerge')
assert r6_vm is not None and 'val' not in r6_vm.attrib, "R6 vMerge错误"
print('✅ 所有验证通过!')
单元格索引映射速查
位置 索引 (行, 列) 字段 说明
基本信息 (0, 0) 授课教师标签 不要修改
基本信息 (0, 1) 授课教师内容 填入姓名
基本信息 (0, 2) 课程名称标签 不要修改
基本信息 (0, 3) 课程名称内容 填入课程名
基本信息 (1, 1) 授课教材 填入教材
基本信息 (2, 1) 授课班级 填入班级
基本信息 (3, 1) 授课内容 填入教学内容
基本信息 (3, 3) 授课时长 填入课时数
目标 (4, 2) 知识目标 多段落列表
目标 (5, 2) 能力目标 多段落列表
目标 (6, 2) 素质目标 多段落列表
思政 (7, 1) 思政元素 多段落列表
重点难点 (8, 1) 教学重点与难点 多段落列表
教法学法 (9, 1) 教法和学法 多段落列表
教学过程 (12, 0) 教学环节与内容 多段落列表
教学过程 (12, 1) 教师活动 多段落列表
教学过程 (12, 2) 学生活动 多段落列表
作业 (13, 1) 课后作业 多段落列表
作业 (13, 3) 评价方式 多段落列表
反思 (14, 1) 教学反思与改进 多段落列表
注意: 所有索引均为 0-based。
课程名称推断规则
根据教案主题关键词自动推断课程名称:
主题关键词 推断课程名称
MOS/MOSFET/NMOS/PMOS/CMOS/半导体/JFET 模拟电子技术基础
51单片机/定时器/中断/Keil/AT89S51/PWM 单片机原理与应用
C语言/指针/数组/结构体/链表 C程序设计
数字电路/逻辑门/触发器/Karnaugh/布尔 数字电子技术基础
传感器/ADC/DAC/滤波/运算放大器 传感器与检测技术
自动控制/PID/传递函数/频域/根轨迹 自动控制原理
通信原理/调制解调/香农/信道编码 通信原理
微机原理/汇编/总线/中断/接口 微机原理与接口技术
信号与系统/傅里叶/拉普拉斯/Z变换 信号与系统
电机/变压器/电力电子/逆变器 电力电子技术
PLC/梯形图/步进电机/伺服 PLC应用技术
PCB/Altium/布线/封装/EDA EDA技术与PCB设计
嵌入式/Linux/ARM/RTOS/STM32 嵌入式系统设计
无线/WIFI/BLE/LoRa/NB-IoT/物联网 物联网技术概论
人工智能/深度学习/神经网络/卷积 人工智能基础
数据库/SQL/ER图/事务/索引 数据库原理与应用
计算机网络/TCP/IP/OSI/路由协议 计算机网络
其他未匹配 根据主题自行推断合理课程名
推断逻辑: 提取主题中的核心技术词,对照关键词表匹配课程名。
教案内容编写指南
教学环节应覆盖
导入新课(5-10% 课时)— 情境创设、问题引入、激发兴趣
知识讲授(30-40% 课时)— 分小节讲解核心知识点
原理分析(15-20% 课时)— 深入讲解原理
实例演示(10-15% 课时)— 结合案例或代码演示
课堂练习(10-15% 课时)— 学生动手实践
课堂小结(5分钟)— 知识梳理、重点回顾
布置作业(5分钟)— 课后巩固、预习引导
教师活动要素
展示(PPT/实物/图片/视频)→ 讲授(板书/讲解/推导)→ 演示(操作/编程/实验)→ 提问(引导思考/检查理解)→ 指导(巡视/答疑/点评)→ 总结(归纳/思维导图)
学生活动要素
观察(看演示/看图片/看动画)→ 思考(回答问题/分析案例)→ 记录(笔记/公式/流程图)→ 操作(编程/实验/计算)→ 讨论(小组交流/互助)→ 练习(独立完成/互评)
注意事项(重要!)
⛔ 禁止使用 python-docx 写入内容(会破坏 vMerge 纵向合并单元格)
✅ 必须使用 zipfile + lxml 直接操作 XML
⚠️ lxml 的 element.set(namespace, key, value) 三个参数用逗号分隔,不是嵌套括号
字体统一为宋体,字号 10.5pt(XML 中 sz=21)
教学环节与教学内容列的段落用左对齐,表头用居中
所有单元格索引用 0-based:(row_index, cell_index)
不要修改原有标签单元格的内容(如"授课教师"、"1.4教学目标"等)
写完后务必验证 vMerge 是否完整、行数是否正确
长文本使用列表格式:['段落1', '段落2', '', '段落3'],空字符串表示分段
常见问题
Q: 为什么不用 python-docx?
A: python-docx 在处理 .docx 时会重新生成 XML,过程中丢失 vMerge 属性。vMerge 是 Word 表格纵向合并单元格的标记,丢失后合并单元格会展开为独立单元格,整个表格结构崩溃。使用 zipfile+lxml 直接操作 XML 可以完全保留原始格式。
Q: 如果模板不是中专教案模板版本怎么办?
A: 本技能专为中专教案模板(15行表格)设计。如使用其他模板,需先分析模板结构,调整行索引和单元格索引映射。
Q: 如何添加新的主题课程?
A: 在课程名称推断规则表中添加新的关键词映射即可。
地理课程规划助手
生物与地理考试复习规划器