周报 Word 文档生成器
把零散的每日工作清单,转成一份格式与该使用者历史周报完全一致的报送版 Word。
核心原则:格式不假设,先从使用者自己的历史周报里反推,再套用。 不同部门、不同岗位的列数、分层标签、固定措辞、缩进规则都可能不同,一律以 profile.json 为准。
用户直接上传历史周报时(最常见)
用户会在对话里直接上传 1–5 份 docx。此时:
-
先确认拿到本地路径。上传的文件落在会话的上传目录里,用
glob/ls找到实际的.docx绝对路径;不要凭空假设路径。 -
把它们放进一个独立文件夹(避免和工作清单、其他文件混在一起),然后照常跑
analyze_reports.py。 -
样本少于 3 份也能跑,但置信度更低——务必逐条核对「需人工确认」,必要时让用户再补一两份。
-
优先挑最新的 3–5 份。用户的历史周报往往改过版,混着分析会让分层结构判断错乱。
-
用户上传的往往是「最新定稿的 1 份 + 清单」,此时直接用
--仅最新即可,但要把列定位结果念给用户确认一遍。
用户上传 N 份周报
↓
确认每份的本地路径(glob 实际落盘位置)
↓
python scripts/analyze_reports.py <这些文件的父目录> --仅最新 -o profile.json
↓
逐条核对「需人工确认」→ 把结论念给用户 → 用户认可
↓
以后每期:清单 + profile.json → spec.json → gen_report.py
列定位关键词表(异形表头靠这个匹配)
不同部门对同样的列叫法差别很大,按关键词模糊匹配而不是按位置写死:
| 角色 | 关键词(任一命中) |
|---|---|
| 姓名/责任列 | 事项、责任、主体、部门、姓名 |
| 内容列 | 工作内容、进展、完成情况、本期工作、工作完成 |
| 计划列 | 下周、下期、下一步、下阶段、后续、计划 |
| 反思列 | 效果评价、评价、成效、存在问题、不足、反思 |
⚠️ 定位顺序必须是:姓名列 → 内容列 → 计划列 → 反思列,且反思列要排除前面已占用的列。
否则「本周工作内容、进展及措施,存在问题」里的"问题"会被误判成反思列。
⚠️ 表头文字常被 Word 拆成多个 run/段落,匹配前必须把单元格内所有 <w:t> 拼起来再判断。
首次使用(或换人)· 建档
每个使用者只需建档一次:
python scripts/analyze_reports.py "<该使用者的历史周报目录>" -o profile.json
可选参数:--包含 "姓名片段"(一个目录里混多人时用)、--仅最新(只取格式最新的那份)。
脚本输出 profile.json 草稿,并列出 需人工确认 条目。逐条处理完再进入生成流程——不要跳过,否则会套错格式。常见待确认项:
-
内容布局.分层标签为空或只识别到一个 → 打开基准文件目视补齐 -
标签行缩进/条目行缩进为 null → 目视确认后填true/false -
提示"样本包含两种分层" → 历史周报改过版,改用
--仅最新或精确筛选后重跑 -
未识别到
数据句模板→ 若该周报本来就有数据句,手工补一条
同时确认 基准文件 指向格式最新且已定稿的那一份。
日常生成流程
1. 读工作清单
清单通常是无表格的纯段落 docx。用 editor_sdk 读取:
python <edsdk.py 路径> call doc_resolve_document_structure --json-file args.json
args.json:{"file_id": "<清单正斜杠路径>", "text_preview_length": 200, "limit": 0, "mode": "compact"}
text_preview_length=200 + limit=0 必须传,否则每段只回 10 个字符。路径必须用正斜杠;反斜杠会生成混合分隔符的 file_id,导致后续 JSON 转义失败。
2. 把清单归类
按 references/writing-rules.md 把每条记录归入:本期重点 / 本条例行 / 问题反思 / 下期计划。要点:
-
成果先于动作:写"做了什么 → 得到什么",不写"参加了会""看了文件"
-
有数字才写数字:清单里没有的量一律留
XXX,绝不编造 -
问题反思必写一句,且下期计划要有对应整改条目(问题—整改闭环)
-
清单里没有公众号/视频号发布数据时,不要硬凑数据句,直接略过(
数据句模板是可选的)
3. 写 spec.json
两种模式,取决于 profile.内容布局.模式:
-
single(内容列内按分层标签组织,如"重点工作/例行工作")→ 用sections -
per_line(每个业务条线占一行,如"宣传工作/党建工作/信访维稳")→ 用行
样例见 assets/spec.single.example.json 与 assets/spec.perline.example.json。条目可直接写 1.xxx;不带编号时按顺序自动编号。
4. 生成
python scripts/gen_report.py profile.json spec.json "<输出docx完整路径>"
输出文件名按 profile.文件命名模板 套 {姓名}{部门}{本期}{下期}。
5. 校验(必做)
生成后逐段复核,确认段数、缩进、文字与 spec 一致。常用检查点:
-
内容格段数 = 标签数 + 条目数 +(分层间空行数)
-
标签行缩进符合
profile.内容布局.标签行缩进,条目行符合条目行缩进 -
问题反思落在
profile.问题反思列指定的那一列 -
生成的 docx 能被 editor_sdk 正常 open_file + doc_get_table_info(防 zip 结构损坏)
-
打开确认视觉效果:重点/例行之间是否有空行分隔、标签是否顶格
硬性约束
-
不得编造数字:清单没有的数据留
XXX -
不得把计划写成已完成
-
不得从空白新建 docx:一律以 profile.基准文件为模板复制,保住字体/字号/行距/列宽/边框
-
改文件名、改内容前先确认输出路径,不要覆盖历史周报
技术要点(详见 references/formatting-howto.md)
-
editor_sdk 的
doc_set_table_cells会丢弃单元格内\n,且表格不允许用坐标类工具拆段 → 多段落排版只能在 docx 文件层做 -
提取单元格文字的正则必须写
<w:t(?:\s[^>]*)?>;写成<w:t[^>]*>会误匹配<w:tcPr>/<w:tabs>,把 XML 当正文写回变成乱码 -
整格替换段落时必须保留
</w:tc>收尾标签,否则后续单元格索引整体错位 -
生成新
<w:p>时不要复制w14:paraId(会重复),直接省略该属性 -
表格解析要按
<w:tr>分行、再按<w:tc>分列;直接把单元格拉平成一维会导致列数/表头全错 -
single 模式也必须写"下期计划"列,否则会残留模板里的旧内容;spec 未提供
下期时脚本会告警 -
Word/WPS 打开文档会生成
~$开头的锁文件,不是有效 zip;脚本已自动跳过,遇到"文件不是 zip"先查这个 -
改标题日期时按出现顺序替换(第1组=本期、第2组=下期),不要假设写的是"近两周/下两周"
参考
-
references/writing-rules.md—— 表达与写作规则(成果写法、数据句、问题反思、固定措辞) -
references/formatting-howto.md—— docx 排版实现细节与踩坑清单 -
assets/profile.example.json—— profile 字段说明 -
assets/spec.single.example.json/assets/spec.perline.example.json—— spec 样例