修正联合行文标志与参数校验
@@ -106,7 +106,7 @@ node scripts/verify_gongwen_docx.mjs --input /tmp/formal.docx --profile formal -
|
|||||||
|
|
||||||
只有需要完整电子红头文件时,才加 `--letterhead digital`。红头和标题要使用目标电脑中实际安装的小标宋体;生成器缺少小标宋体或仿宋体时会在终端明确警告并写出替代字体,要求严格阻止替代输出时加 `--require-standard-fonts`。红线下标题会写入两个显式的28磅版心空行,不会依赖渲染器自行解释段前距;发文机关标志到文号也按相同方式留出两行。上行文的文号和签发人会在同一行编排。打开文档后,Word/WPS 的“引用→目录”可以按“标题1—标题4”生成并更新目录;是否显示第四级,在目录设置中选择。
|
只有需要完整电子红头文件时,才加 `--letterhead digital`。红头和标题要使用目标电脑中实际安装的小标宋体;生成器缺少小标宋体或仿宋体时会在终端明确警告并写出替代字体,要求严格阻止替代输出时加 `--require-standard-fonts`。红线下标题会写入两个显式的28磅版心空行,不会依赖渲染器自行解释段前距;发文机关标志到文号也按相同方式留出两行。上行文的文号和签发人会在同一行编排。打开文档后,Word/WPS 的“引用→目录”可以按“标题1—标题4”生成并更新目录;是否显示第四级,在目录设置中选择。
|
||||||
|
|
||||||
信函、命令(令)、纪要和横排表格走专用分支:信函生成170mm上粗下细、下页边20mm处上细下粗的两条红色双线,底线放在页脚并关闭页码;命令(令)落实机关标志距版心上边缘20mm、令号下空二行、正文下空二行;纪要把“出席”“请假”“列席”标签设为黑体、人员名单设为仿宋,并放在正文或附件说明下一行;横排表格生成横向A4和225mm表格,单双页表头方向仍需目标Word/WPS模板核对。联合行文可重复传入 `--joint-org`,不能与正文一起装订的附件加 `--attachment-detached` 会在首行补排文号和附件序号。附件可用重复的 `--attachment-file` 另页生成“附件”标签、第三行标题和正文,并保持正式页码连续。带抄送或印发信息时,版记浮动锚定在最后一页版心底部,首末粗线约0.35mm、中间细线约0.25mm。
|
信函、命令(令)、纪要和横排表格走专用分支:信函生成170mm上粗下细、下页边20mm处上细下粗的两条红色双线,底线放在页脚并关闭页码;命令(令)落实机关标志距版心上边缘20mm、令号下空二行、正文下空二行;纪要把“出席”“请假”“列席”标签设为黑体、人员名单设为仿宋,并放在正文或附件说明下一行;横排表格生成横向A4和225mm表格,单双页表头方向仍需目标Word/WPS模板核对。联合行文可重复传入 `--joint-org`,生成主办机关在前、联署机关名称分行排列且“文件”置右并上下居中的标志;不能与正文一起装订的附件加 `--attachment-detached` 会在首行补排文号和附件序号。附件可用重复的 `--attachment-file` 另页生成“附件”标签、第三行标题和正文,并保持正式页码连续。带抄送或印发信息时,版记浮动锚定在最后一页版心底部,首末粗线约0.35mm、中间细线约0.25mm。
|
||||||
|
|
||||||
## 跨平台安装
|
## 跨平台安装
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ GB/T 9704-2012《党政机关公文格式》现行,2025-05-30 复审继续有
|
|||||||
|
|
||||||
本工具只处理排版,不判断单位身份、授权状态或后续盖章方式。它会根据用户明确选择的版式模式应用对应的排版规则,不因“正式”“国企”“报告”或仅提供机构名称而擅自使用红头。
|
本工具只处理排版,不判断单位身份、授权状态或后续盖章方式。它会根据用户明确选择的版式模式应用对应的排版规则,不因“正式”“国企”“报告”或仅提供机构名称而擅自使用红头。
|
||||||
|
|
||||||
生成器可输出 A4、156mm×225mm 版心、三号仿宋正文、小标宋二号标题、四级标题层次、两字缩进,以及居中或单双页页码。四级标题均写入 Word/WPS 标题样式和大纲级别,便于后续插入、更新目录;文章总标题使用独立“公文标题”样式,不进入目录。上行文的文号和签发人在同一行编排,左右各空一字;信函、命令(令)、纪要和横排表格使用各自专用版式;电子联合行文可重复传入 `--joint-org`,分离装订附件可加 `--attachment-detached`;重复传入 `--attachment-file` 时必须同时提供与附件顺序、标题一致的 `--attachment-note`,附件会另页生成并保持页码连续。版记会锚定最后一页版心底部,正式页码按版心下边缘下7mm的位置生成。正式版头的份号、密级、紧急程度和电子机关标志以版心上边缘为垂直锚点固定定位,不会因为左上字段而把机关标志或预印红头留白向下推移。只有传入密级而未传入份号时,首行会保留空位,密级仍从第二行开始。
|
生成器可输出 A4、156mm×225mm 版心、三号仿宋正文、小标宋二号标题、四级标题层次、两字缩进,以及居中或单双页页码。四级标题均写入 Word/WPS 标题样式和大纲级别,便于后续插入、更新目录;文章总标题使用独立“公文标题”样式,不进入目录。上行文的文号和签发人在同一行编排,左右各空一字;信函、命令(令)、纪要和横排表格使用各自专用版式;电子联合行文可重复传入 `--joint-org`;主办机关在前,联署机关名称分行排列,“文件”置右并按联署名称上下居中;分离装订附件可加 `--attachment-detached`;重复传入 `--attachment-file` 时必须同时提供与附件顺序、标题一致的 `--attachment-note`,附件会另页生成并保持页码连续。版记会锚定最后一页版心底部,正式页码按版心下边缘下7mm的位置生成。正式版头的份号、密级、紧急程度和电子机关标志以版心上边缘为垂直锚点固定定位,不会因为左上字段而把机关标志或预印红头留白向下推移。只有传入密级而未传入份号时,首行会保留空位,密级仍从第二行开始。
|
||||||
|
|
||||||
`references/formal-checklist.md` 是可选的版式复核清单。涉及印章或签名章时,使用者可在 Word/WPS 中插入已取得的图片或完成实体盖章;本生成器不内置印章图像。
|
`references/formal-checklist.md` 是可选的版式复核清单。涉及印章或签名章时,使用者可在 Word/WPS 中插入已取得的图片或完成实体盖章;本生成器不内置印章图像。
|
||||||
|
|
||||||
@@ -35,7 +35,7 @@ node scripts/generate_gongwen_docx.mjs --input source.md --output output.docx --
|
|||||||
node scripts/generate_gongwen_docx.mjs --input source.md --output output.docx --format formal --letterhead digital --org "发文机关名称" --doc-no "单位发〔2026〕1号" --title "文档标题"
|
node scripts/generate_gongwen_docx.mjs --input source.md --output output.docx --format formal --letterhead digital --org "发文机关名称" --doc-no "单位发〔2026〕1号" --title "文档标题"
|
||||||
```
|
```
|
||||||
|
|
||||||
`letter`、`command`、`minutes`、`horizontal-table` 分别对应信函、命令(令)、纪要和横排表格格式;需要时显式传入 `--format` 和相应字段。横排表格会生成横向A4页面和225mm表格,单双页表头在订口/切口的朝向仍需目标 Word/WPS 模板核对。联合行文使用 `--joint-org`;附件不能与正文一起装订时使用 `--attachment-detached`,附件首行会补排文号和附件序号。`command` 会要求机关标志以“命令”或“令”结尾;信函中的份号、密级和紧急程度会在第一条双线下按标准顺序编排,联合行文和机关专用信函模板仍需目标软件核对。正式发文默认单双页页码;`standard` 为单页右、双页左,`center` 与 `none` 供普通材料选择。
|
`letter`、`command`、`minutes`、`horizontal-table` 分别对应信函、命令(令)、纪要和横排表格格式;需要时显式传入 `--format` 和相应字段。横排表格会生成横向A4页面和225mm表格,单双页表头在订口/切口的朝向仍需目标 Word/WPS 模板核对。联合行文使用 `--joint-org`,主办机关在前、联署机关名称分行排列,“文件”置右并按联署名称上下居中;附件不能与正文一起装订时使用 `--attachment-detached`,附件首行会补排文号和附件序号。`command` 会要求机关标志以“命令”或“令”结尾;信函中的份号、密级和紧急程度会在第一条双线下按标准顺序编排,联合行文和机关专用信函模板仍需目标软件核对。正式发文默认单双页页码;`standard` 为单页右、双页左,`center` 与 `none` 供普通材料选择。
|
||||||
|
|
||||||
附件可重复传入 `--attachment-file attachment.md`。附件 Markdown 的首个一级标题会作为附件标题,第一页第一行写“附件1”(后续文件递增),第三行写标题,随后排正文;附件说明通过 `--attachment-note` 提供,工具会统一为“附件:”并去除末尾标点,同时拒绝顺序或标题与附件文件不一致的输入。复杂横排附件、不能与正文一起装订的附件和机关专用模板仍需在目标 Word/WPS 中核对。
|
附件可重复传入 `--attachment-file attachment.md`。附件 Markdown 的首个一级标题会作为附件标题,第一页第一行写“附件1”(后续文件递增),第三行写标题,随后排正文;附件说明通过 `--attachment-note` 提供,工具会统一为“附件:”并去除末尾标点,同时拒绝顺序或标题与附件文件不一致的输入。复杂横排附件、不能与正文一起装订的附件和机关专用模板仍需在目标 Word/WPS 中核对。
|
||||||
|
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 160 KiB After Width: | Height: | Size: 159 KiB |
|
Before Width: | Height: | Size: 39 KiB After Width: | Height: | Size: 41 KiB |
|
Before Width: | Height: | Size: 270 KiB After Width: | Height: | Size: 356 KiB |
|
Before Width: | Height: | Size: 57 KiB After Width: | Height: | Size: 56 KiB |
|
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 40 KiB |
|
Before Width: | Height: | Size: 63 KiB After Width: | Height: | Size: 62 KiB |
|
Before Width: | Height: | Size: 152 KiB After Width: | Height: | Size: 151 KiB |
|
Before Width: | Height: | Size: 106 KiB After Width: | Height: | Size: 108 KiB |
|
Before Width: | Height: | Size: 146 KiB After Width: | Height: | Size: 147 KiB |
|
Before Width: | Height: | Size: 64 KiB After Width: | Height: | Size: 65 KiB |
|
Before Width: | Height: | Size: 142 KiB After Width: | Height: | Size: 128 KiB |
|
Before Width: | Height: | Size: 64 KiB After Width: | Height: | Size: 85 KiB |
|
Before Width: | Height: | Size: 344 KiB After Width: | Height: | Size: 376 KiB |
|
Before Width: | Height: | Size: 183 KiB After Width: | Height: | Size: 197 KiB |
|
Before Width: | Height: | Size: 168 KiB After Width: | Height: | Size: 167 KiB |
|
Before Width: | Height: | Size: 39 KiB After Width: | Height: | Size: 41 KiB |
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 179 KiB After Width: | Height: | Size: 179 KiB |
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 44 KiB |
|
Before Width: | Height: | Size: 189 KiB After Width: | Height: | Size: 190 KiB |
|
Before Width: | Height: | Size: 172 KiB After Width: | Height: | Size: 172 KiB |
|
Before Width: | Height: | Size: 186 KiB After Width: | Height: | Size: 186 KiB |
|
Before Width: | Height: | Size: 39 KiB After Width: | Height: | Size: 39 KiB |
|
Before Width: | Height: | Size: 182 KiB After Width: | Height: | Size: 182 KiB |
|
Before Width: | Height: | Size: 248 KiB After Width: | Height: | Size: 227 KiB |
|
Before Width: | Height: | Size: 51 KiB After Width: | Height: | Size: 50 KiB |
@@ -52,7 +52,7 @@
|
|||||||
- [ ] 印发机关和日期为四号仿宋,左空一字与右空一字;日期完整且不补零,后加“印发”。
|
- [ ] 印发机关和日期为四号仿宋,左空一字与右空一字;日期完整且不补零,后加“印发”。
|
||||||
- [ ] 页码为四号半角宋体阿拉伯数字,两侧各一字线,线距版心下边缘7mm;单页右空一字、双页左空一字;空白页、特定版记页和附件连续页码已按规则处理。
|
- [ ] 页码为四号半角宋体阿拉伯数字,两侧各一字线,线距版心下边缘7mm;单页右空一字、双页左空一字;空白页、特定版记页和附件连续页码已按规则处理。
|
||||||
- [ ] 横排表格使用 `--format horizontal-table` 或目标 Word/WPS 横向模板;本项目已实际渲染横向页面和225mm表格,但单双页表头在订口/切口的方向仍需目标软件核对。
|
- [ ] 横排表格使用 `--format horizontal-table` 或目标 Word/WPS 横向模板;本项目已实际渲染横向页面和225mm表格,但单双页表头在订口/切口的方向仍需目标软件核对。
|
||||||
- [ ] 信函、命令(令)、纪要、联合行文已使用相应专用版式;`formal --joint-org` 的截图已确认主办机关在前,复杂机关标志仍按现行模板核对;不能用普通打印稿替代。
|
- [ ] 信函、命令(令)、纪要、联合行文已使用相应专用版式;`formal --joint-org` 的截图已确认主办机关在前、联署机关分行排列且“文件”置右并上下居中;复杂机关标志仍按现行模板核对;不能用普通打印稿替代。
|
||||||
- [ ] 信函格式已核对上边缘30mm、上粗下细双线、下页边20mm处上细下粗双线,双线长度均170mm;如有份号、密级、紧急程度,均置于第一条双线下并距线3号字高7/8;文号顶格居右;首页无页码且版记不画分隔线。当前生成器对这些可选信函版头字段要求使用专用模板。
|
- [ ] 信函格式已核对上边缘30mm、上粗下细双线、下页边20mm处上细下粗双线,双线长度均170mm;如有份号、密级、紧急程度,均置于第一条双线下并距线3号字高7/8;文号顶格居右;首页无页码且版记不画分隔线。当前生成器对这些可选信函版头字段要求使用专用模板。
|
||||||
- [ ] 命令(令)格式已核对发文机关全称加“命令”或“令”、标志上边缘距版心20mm、令号下空二行、正文下空二行;签发章和日期按7.3.5.3核对。
|
- [ ] 命令(令)格式已核对发文机关全称加“命令”或“令”、标志上边缘距版心20mm、令号下空二行、正文下空二行;签发章和日期按7.3.5.3核对。
|
||||||
- [ ] 纪要格式已核对标志上边缘距版心35mm,出席/请假/列席标签为黑体,人员为仿宋。
|
- [ ] 纪要格式已核对标志上边缘距版心35mm,出席/请假/列席标签为黑体,人员为仿宋。
|
||||||
|
|||||||
@@ -160,7 +160,7 @@
|
|||||||
| 预印红头纸套打 | 是 | `--format formal --letterhead preprinted`,按纸样设置预留高度 |
|
| 预印红头纸套打 | 是 | `--format formal --letterhead preprinted`,按纸样设置预留高度 |
|
||||||
| 完整电子红头 | 是 | `--format formal --letterhead digital` |
|
| 完整电子红头 | 是 | `--format formal --letterhead digital` |
|
||||||
| 印章、签名章 | 文字版式之外 | 在 Word/WPS 中插入图片或实体盖章 |
|
| 印章、签名章 | 文字版式之外 | 在 Word/WPS 中插入图片或实体盖章 |
|
||||||
| 联合行文 | 通过 `--joint-org` 同行生成,主办机关在前 | 复杂机关专用标志和联署模板复核 |
|
| 联合行文 | 通过 `--joint-org` 分行生成,主办机关在前,“文件”置右并按联署名称上下居中 | 复杂机关专用标志和联署模板复核 |
|
||||||
| 附件 | 通过 `--attachment-file` 另页生成标签、标题和正文;`--attachment-detached` 补排文号和附件序号 | 复杂附件版式仍需人工复核 |
|
| 附件 | 通过 `--attachment-file` 另页生成标签、标题和正文;`--attachment-detached` 补排文号和附件序号 | 复杂附件版式仍需人工复核 |
|
||||||
| 版记 | 是 | `--cc`、`--print-org`、`--print-date` 适用时生成 |
|
| 版记 | 是 | `--cc`、`--print-org`、`--print-date` 适用时生成 |
|
||||||
| 信函、命令、纪要、横排表格 | 是/部分通过 | `--format letter|command|minutes|horizontal-table`,按实际字段生成;横排表头方向需模板复核 |
|
| 信函、命令、纪要、横排表格 | 是/部分通过 | `--format letter|command|minutes|horizontal-table`,按实际字段生成;横排表头方向需模板复核 |
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
| 7.2.1 | 份号六位、3 号、左上第一行 | `--copy-no` 只接受 1—6 位阿拉伯数字并补足六位 | 结构检查;实际是否需要份号由发文机关确认 |
|
| 7.2.1 | 份号六位、3 号、左上第一行 | `--copy-no` 只接受 1—6 位阿拉伯数字并补足六位 | 结构检查;实际是否需要份号由发文机关确认 |
|
||||||
| 7.2.2 | 密级和保密期限第二行、3 号黑体 | `--secret` 按黑体3号写入;没有份号时自动保留第一行空位,使密级仍在第二行 | 结构检查和视觉审计;文字内容和期限写法人工复核 |
|
| 7.2.2 | 密级和保密期限第二行、3 号黑体 | `--secret` 按黑体3号写入;没有份号时自动保留第一行空位,使密级仍在第二行 | 结构检查和视觉审计;文字内容和期限写法人工复核 |
|
||||||
| 7.2.3 | 紧急程度及排列顺序 | `--urgent` 按黑体 3 号写入,并按份号、密级、紧急程度顺序下移 | 适用性和紧急级别人工确认 |
|
| 7.2.3 | 紧急程度及排列顺序 | `--urgent` 按黑体 3 号写入,并按份号、密级、紧急程度顺序下移 | 适用性和紧急级别人工确认 |
|
||||||
| 7.2.4 | 发文机关标志居中、红色、版心上边缘下 35mm、推荐小标宋 | `formal --letterhead digital` 才绘制;预印模式只留纸样区域;首面字段以版心上边缘为垂直锚点,机关标志固定在其下35mm,不推动机关标志或预留区;联合行文通过 `--joint-org` 同行生成,主办机关在前,名称过长时自适应标志字号 | `verify_gongwen_docx.mjs`、`tests/measure-header-coordinates.mjs` 和[`gbt9704-screenshot-evidence.md`](gbt9704-screenshot-evidence.md);当前机缺少推荐字体时严格模式失败,复杂机关专用标志仍需模板核对 |
|
| 7.2.4 | 发文机关标志居中、红色、版心上边缘下 35mm、推荐小标宋 | `formal --letterhead digital` 才绘制;预印模式只留纸样区域;首面字段以版心上边缘为垂直锚点,机关标志固定在其下35mm,不推动机关标志或预留区;联合行文通过 `--joint-org` 分行生成,主办机关在前,“文件”置右并按联署名称上下居中;名称过长时自适应标志字号 | `verify_gongwen_docx.mjs`、`tests/measure-header-coordinates.mjs` 和[`gbt9704-screenshot-evidence.md`](gbt9704-screenshot-evidence.md);当前机缺少推荐字体时严格模式失败,复杂机关专用标志仍需模板核对 |
|
||||||
| 7.2.5 | 文号下空二行、六角括号、全年份、顺序号不加“第”不补零 | `formal`/`letter` 对 `--doc-no` 做格式校验,并写入两个显式 28 磅空行 | 文号语义由机关编号规则确认 |
|
| 7.2.5 | 文号下空二行、六角括号、全年份、顺序号不加“第”不补零 | `formal`/`letter` 对 `--doc-no` 做格式校验,并写入两个显式 28 磅空行 | 文号语义由机关编号规则确认 |
|
||||||
| 7.2.6 | 上行文文号左空一字、签发人右空一字并同一行;标签仿宋、姓名楷体 | `--upward true --signer` 同行生成单一或两个签发人,左右各空一字;多签发人、联合行文转人工模板 | 结构校验和 PDF;复杂联合行文需按机关顺序人工排布 |
|
| 7.2.6 | 上行文文号左空一字、签发人右空一字并同一行;标签仿宋、姓名楷体 | `--upward true --signer` 同行生成单一或两个签发人,左右各空一字;多签发人、联合行文转人工模板 | 结构校验和 PDF;复杂联合行文需按机关顺序人工排布 |
|
||||||
| 7.2.7 | 文号下 4mm、版心等宽红线 | `redRule()` 生成 156mm 红线,文号段后 4mm;预印模式不重绘 | PDF 量测;红色油墨和实际纸样人工核对 |
|
| 7.2.7 | 文号下 4mm、版心等宽红线 | `redRule()` 生成 156mm 红线,文号段后 4mm;预印模式不重绘 | PDF 量测;红色油墨和实际纸样人工核对 |
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ bash tests/visual-audit.sh /tmp/gongwen-visual-audit-all-rules
|
|||||||
| 7.2.1 | 份号六位三号阿拉伯数字,版心左上第一行。 | `formal-digital-all-1.png`、`formal-preprinted-1.png` 显示 `000007`;独立坐标日志显示 39.88mm 首行位置。 | 截图通过。 |
|
| 7.2.1 | 份号六位三号阿拉伯数字,版心左上第一行。 | `formal-digital-all-1.png`、`formal-preprinted-1.png` 显示 `000007`;独立坐标日志显示 39.88mm 首行位置。 | 截图通过。 |
|
||||||
| 7.2.2 | 密级和保密期限第二行三号黑体,数字用阿拉伯数字。 | `formal-digital-all-1.png` 显示 `机密★3年` 位于第二行。 | 截图通过;密级文字及期限是否适用需机关确认。 |
|
| 7.2.2 | 密级和保密期限第二行三号黑体,数字用阿拉伯数字。 | `formal-digital-all-1.png` 显示 `机密★3年` 位于第二行。 | 截图通过;密级文字及期限是否适用需机关确认。 |
|
||||||
| 7.2.3 | 紧急程度三号黑体;与份号、密级同时出现时按份号、密级、紧急程度自上而下。 | `formal-digital-all-1.png` 显示三项顺序;`letter-fields-1.png` 显示信函双线下同顺序。 | 截图通过。 |
|
| 7.2.3 | 紧急程度三号黑体;与份号、密级同时出现时按份号、密级、紧急程度自上而下。 | `formal-digital-all-1.png` 显示三项顺序;`letter-fields-1.png` 显示信函双线下同顺序。 | 截图通过。 |
|
||||||
| 7.2.4 | 机关全称/规范简称可加“文件”,居中红色;上边缘距版心上边缘35mm;联合行文主办机关在前,联署名称上下居中。 | `formal-digital-all-1.png`、`formal-joint-1.png`;坐标日志显示机关标志 71.41mm 页面坐标,字段差0.00mm;联合行文以主办机关在前并自适应同一行字号。 | 截图通过,推荐小标宋字体需目标机复核;复杂机关专用标志仍需模板核对。 |
|
| 7.2.4 | 机关全称/规范简称可加“文件”,居中红色;上边缘距版心上边缘35mm;联合行文主办机关在前,联署名称上下居中。 | `formal-digital-all-1.png`、`formal-joint-1.png`;坐标日志显示机关标志 71.41mm 页面坐标,字段差0.00mm;联合行文以主办机关在前、联署机关名称分行排列,“文件”置右并按联署名称上下居中;名称过长时自适应标志字号。 | 截图通过,推荐小标宋字体需目标机复核;复杂机关专用标志仍需模板核对。 |
|
||||||
| 7.2.5 | 机关标志下空二行;年份全称、六角括号、顺序号不加“第”不补零、末尾“号”;上行文文号左空一字。 | `formal-digital-all-1.png`、`formal-digital-upward-1.png`;文号输入边界和显式空行均经校验。 | 截图通过。 |
|
| 7.2.5 | 机关标志下空二行;年份全称、六角括号、顺序号不加“第”不补零、末尾“号”;上行文文号左空一字。 | `formal-digital-all-1.png`、`formal-digital-upward-1.png`;文号输入边界和显式空行均经校验。 | 截图通过。 |
|
||||||
| 7.2.6 | “签发人:”三号仿宋、姓名三号楷体,右空一字;多签发人按顺序、一般每行两名、回行对齐。 | `formal-digital-upward-1.png` 显示同一行双签发人,姓名字体和标签分 run。 | 截图通过;超过两名或联合行文复杂签发人仍须专用模板。 |
|
| 7.2.6 | “签发人:”三号仿宋、姓名三号楷体,右空一字;多签发人按顺序、一般每行两名、回行对齐。 | `formal-digital-upward-1.png` 显示同一行双签发人,姓名字体和标签分 run。 | 截图通过;超过两名或联合行文复杂签发人仍须专用模板。 |
|
||||||
| 7.2.7 | 文号下4mm处、版心等宽红色分隔线。 | `formal-digital-all-1.png`、`formal-joint-1.png`;线宽156mm,红线下标题空两行。 | 截图通过;预印模式明确不重绘红线。 |
|
| 7.2.7 | 文号下4mm处、版心等宽红色分隔线。 | `formal-digital-all-1.png`、`formal-joint-1.png`;线宽156mm,红线下标题空两行。 | 截图通过;预印模式明确不重绘红线。 |
|
||||||
@@ -98,7 +98,7 @@ bash tests/visual-audit.sh /tmp/gongwen-visual-audit-all-rules
|
|||||||
## 本次发现并修正的实现问题
|
## 本次发现并修正的实现问题
|
||||||
|
|
||||||
1. 命令(令)分支曾把20mm误当成纸张上边距,导致机关标志距离纸顶约20mm;现在恢复标准37mm天头,并在版心上边缘下20mm处排标志,实际截图已复核。
|
1. 命令(令)分支曾把20mm误当成纸张上边距,导致机关标志距离纸顶约20mm;现在恢复标准37mm天头,并在版心上边缘下20mm处排标志,实际截图已复核。
|
||||||
2. 联合行文曾把联署机关名称拆成多行,容易把“上下居中”误做成额外机关标志行;现在主办机关在前,联署名称同一居中行,自适应较小标志字号以保持一行。
|
2. 联合行文曾把联署机关名称错误压成同一横行;现在主办机关在前、联署机关名称分行排列,“文件”置右并按联署名称上下居中,名称过长时自适应标志字号。
|
||||||
3. 纪要出席、请假、列席名单曾追加在附件和版记之后;现在紧跟正文或附件说明下一行生成,符合10.3的编排位置。
|
3. 纪要出席、请假、列席名单曾追加在附件和版记之后;现在紧跟正文或附件说明下一行生成,符合10.3的编排位置。
|
||||||
4. PDF 字形量测曾按 `yMin` 粗略分组,遇到高字形会把同一视觉行拆开;现在按字形垂直重叠合并后再量测,独立坐标结果稳定。
|
4. PDF 字形量测曾按 `yMin` 粗略分组,遇到高字形会把同一视觉行拆开;现在按字形垂直重叠合并后再量测,独立坐标结果稳定。
|
||||||
5. 视觉审计补入了横排表格、22×28校准页、联合行文、分离装订附件、不盖章公文和命令(令)等场景,不再只依赖电子红头样例。
|
5. 视觉审计补入了横排表格、22×28校准页、联合行文、分离装订附件、不盖章公文和命令(令)等场景,不再只依赖电子红头样例。
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ bash tests/visual-audit.sh /tmp/gongwen-visual-audit-all-rules
|
|||||||
| 7.2.1 | 份号六位、左上第一行 | 截图通过 | `formal-digital-all-1.png` 和 `formal-preprinted-1.png` 显示 `000007`;首面字段采用固定定位。 |
|
| 7.2.1 | 份号六位、左上第一行 | 截图通过 | `formal-digital-all-1.png` 和 `formal-preprinted-1.png` 显示 `000007`;首面字段采用固定定位。 |
|
||||||
| 7.2.2 | 密级和保密期限第二行、3 号黑体 | 截图通过 | `formal-digital-all-1.png` 显示左上第二行;保密期限具体写法仍需机关确认。 |
|
| 7.2.2 | 密级和保密期限第二行、3 号黑体 | 截图通过 | `formal-digital-all-1.png` 显示左上第二行;保密期限具体写法仍需机关确认。 |
|
||||||
| 7.2.3 | 紧急程度及顺序 | 截图通过 | `formal-digital-all-1.png` 显示份号、密级、紧急程度顺序;是否适用由发文机关决定。 |
|
| 7.2.3 | 紧急程度及顺序 | 截图通过 | `formal-digital-all-1.png` 显示份号、密级、紧急程度顺序;是否适用由发文机关决定。 |
|
||||||
| 7.2.4 | 机关标志居中、红色、距版心上边缘 35 mm | 版式结构通过,标准字体需复核 | `formal-digital-all-1.png` 加 `references/assets/visual-audit/header-coordinates.log` 的 PDF 字形量测;左上字段不再推动机关标志。机关标志字体按标准为推荐小标宋,本机缺少该字体,严格模式失败。联合行文标志仍需专用模板。 |
|
| 7.2.4 | 机关标志居中、红色、距版心上边缘 35 mm | 版式结构通过,标准字体需复核 | `formal-digital-all-1.png` 加 `references/assets/visual-audit/header-coordinates.log` 的 PDF 字形量测;左上字段不再推动机关标志。机关标志字体按标准为推荐小标宋,本机缺少该字体,严格模式失败;`formal-joint-1.png` 已观察主办机关在前、联署机关分行排列且“文件”置右并按联署名称上下居中,复杂机关专用标志仍需模板。 |
|
||||||
| 7.2.5 | 文号下空二行、年份、六角括号、序号规则 | 截图通过 | `formal-digital-all-1.png`、`formal-digital-upward-1.png`;输入验证拒绝“第”和前导零。 |
|
| 7.2.5 | 文号下空二行、年份、六角括号、序号规则 | 截图通过 | `formal-digital-all-1.png`、`formal-digital-upward-1.png`;输入验证拒绝“第”和前导零。 |
|
||||||
| 7.2.6 | 上行文签发人及多签发人 | 结构通过,仍需人工 | `formal-digital-upward-1.png` 已见同一行和两个签发人;超过两个签发人或联合行文转机关模板。 |
|
| 7.2.6 | 上行文签发人及多签发人 | 结构通过,仍需人工 | `formal-digital-upward-1.png` 已见同一行和两个签发人;超过两个签发人或联合行文转机关模板。 |
|
||||||
| 7.2.7 | 文号下 4 mm、版心等宽红线 | 截图通过 | `formal-digital-all-1.png` 红线与版心同宽;预印模式不重绘,改由纸样提供。 |
|
| 7.2.7 | 文号下 4 mm、版心等宽红线 | 截图通过 | `formal-digital-all-1.png` 红线与版心同宽;预印模式不重绘,改由纸样提供。 |
|
||||||
@@ -84,7 +84,7 @@ bash tests/visual-audit.sh /tmp/gongwen-visual-audit-all-rules
|
|||||||
|
|
||||||
1. 版头字段曾以普通段落排列,份号、密级、紧急程度会把电子红头机关标志向下推移,预印红头套打的留白也会被挤开。现在这些字段改为首面固定定位,版心中保留等高占位;`formal-digital-all-1.png` 和 `formal-preprinted-1.png` 已重新观察。
|
1. 版头字段曾以普通段落排列,份号、密级、紧急程度会把电子红头机关标志向下推移,预印红头套打的留白也会被挤开。现在这些字段改为首面固定定位,版心中保留等高占位;`formal-digital-all-1.png` 和 `formal-preprinted-1.png` 已重新观察。
|
||||||
2. 命令(令)分支曾把20mm误当成纸顶边距;现在恢复37mm天头,并从版心上边缘下20mm量测。
|
2. 命令(令)分支曾把20mm误当成纸顶边距;现在恢复37mm天头,并从版心上边缘下20mm量测。
|
||||||
3. 联合行文曾把联署机关拆成多行;现在主办机关在前、联署名称同一居中行,并在名称过长时自适应标志字号。
|
3. 联合行文曾把联署机关错误压成同一横行;现在主办机关在前、联署名称分行排列,“文件”置右并按联署名称上下居中,名称过长时自适应标志字号。
|
||||||
4. 纪要人员曾追加在附件和版记之后;现在紧跟正文或附件说明下一行。
|
4. 纪要人员曾追加在附件和版记之后;现在紧跟正文或附件说明下一行。
|
||||||
5. 红线下标题曾只依赖段前距,部分渲染器会把标题贴在线上。现在红线或纸上红线之后写入两个显式 28 磅空段落;截图能看到标题与红线之间的实际距离。
|
5. 红线下标题曾只依赖段前距,部分渲染器会把标题贴在线上。现在红线或纸上红线之后写入两个显式 28 磅空段落;截图能看到标题与红线之间的实际距离。
|
||||||
6. 主送机关带不带末尾冒号时曾可能重复,现在归一化为一行全角冒号。
|
6. 主送机关带不带末尾冒号时曾可能重复,现在归一化为一行全角冒号。
|
||||||
|
|||||||
@@ -134,10 +134,14 @@ function parseArgs(argv) {
|
|||||||
args[name] = true;
|
args[name] = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
const value = argv[i + 1];
|
||||||
|
if (value === undefined || value.startsWith("--")) {
|
||||||
|
throw new Error(`--${name} requires a value`);
|
||||||
|
}
|
||||||
if (repeatable.has(name)) {
|
if (repeatable.has(name)) {
|
||||||
args[name] = [...(args[name] ?? []), argv[i + 1]];
|
args[name] = [...(args[name] ?? []), value];
|
||||||
} else {
|
} else {
|
||||||
args[name] = argv[i + 1];
|
args[name] = value;
|
||||||
}
|
}
|
||||||
i += 1;
|
i += 1;
|
||||||
}
|
}
|
||||||
@@ -786,17 +790,20 @@ function buildDocument(blocks, args) {
|
|||||||
// not move the centered mark upward.
|
// not move the centered mark upward.
|
||||||
const jointOrganizations = Array.isArray(args["joint-org"]) ? args["joint-org"].map((name) => String(name).trim()).filter(Boolean) : [];
|
const jointOrganizations = Array.isArray(args["joint-org"]) ? args["joint-org"].map((name) => String(name).trim()).filter(Boolean) : [];
|
||||||
const agencyNames = [String(args.org).trim(), ...jointOrganizations];
|
const agencyNames = [String(args.org).trim(), ...jointOrganizations];
|
||||||
// GB/T 9704-2012 7.2.4.2 keeps joint agency names on one centered
|
// GB/T 9704-2012 7.2.4 keeps joint agency names in order with the
|
||||||
// mark row, with the host agency first. Full-width spaces preserve a
|
// host first. When “文件” is present it sits to the right of the
|
||||||
// visible separation without creating extra logo rows that would move
|
// stacked names and is vertically centred against that name block.
|
||||||
// the document number and title downward.
|
|
||||||
const host = String(args.org).trim();
|
const host = String(args.org).trim();
|
||||||
|
const jointNames = jointOrganizations.length && host.endsWith("文件")
|
||||||
|
? [host.slice(0, -2), ...jointOrganizations]
|
||||||
|
: agencyNames;
|
||||||
|
const middleIndex = Math.floor((jointNames.length - 1) / 2);
|
||||||
const jointText = jointOrganizations.length && host.endsWith("文件")
|
const jointText = jointOrganizations.length && host.endsWith("文件")
|
||||||
? [...[host.slice(0, -2), ...jointOrganizations], "文件"].join(" ")
|
? jointNames.map((name, index) => index === middleIndex ? `${name} 文件` : name).join("\n")
|
||||||
: agencyNames.join(" ");
|
: agencyNames.join(" ");
|
||||||
const agencyMarkSize = agencyNames.length > 1 ? (jointText.length > 16 ? "44" : "48") : "56";
|
const agencyMarkSize = agencyNames.length > 1 ? (jointText.length > 16 ? "44" : "48") : "56";
|
||||||
body.push(floatingAgencyMarkParagraph(jointText, 1, agencyMarkSize));
|
body.push(floatingAgencyMarkParagraph(jointText, jointOrganizations.length ? jointNames.length : 1, agencyMarkSize));
|
||||||
body.push(agencyMarkFlowSpacer());
|
body.push(agencyMarkFlowSpacer(jointOrganizations.length ? Math.max(0, jointNames.length - 1) * 560 : 0));
|
||||||
if (args["doc-no"]) body.push(...blankGridLines(2));
|
if (args["doc-no"]) body.push(...blankGridLines(2));
|
||||||
}
|
}
|
||||||
if (letterhead === "preprinted") {
|
if (letterhead === "preprinted") {
|
||||||
@@ -1014,7 +1021,13 @@ function writeDocx(output, documentXml, pageNumberMode, format) {
|
|||||||
fs.rmSync(dir, { recursive: true, force: true });
|
fs.rmSync(dir, { recursive: true, force: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
const args = parseArgs(process.argv);
|
let args;
|
||||||
|
try {
|
||||||
|
args = parseArgs(process.argv);
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`GENERATOR ERROR: ${error.message}`);
|
||||||
|
process.exit(2);
|
||||||
|
}
|
||||||
if (args.help || !args.input || !args.output) {
|
if (args.help || !args.input || !args.output) {
|
||||||
usage();
|
usage();
|
||||||
process.exit(args.help ? 0 : 1);
|
process.exit(args.help ? 0 : 1);
|
||||||
|
|||||||
@@ -130,8 +130,16 @@ unzip -p "$TMP_DIR/horizontal-table.docx" word/document.xml | grep -q 'w:tblW w:
|
|||||||
unzip -p "$TMP_DIR/joint.docx" word/document.xml | grep -q '主办机关'
|
unzip -p "$TMP_DIR/joint.docx" word/document.xml | grep -q '主办机关'
|
||||||
unzip -p "$TMP_DIR/joint.docx" word/document.xml | grep -q '协办机关'
|
unzip -p "$TMP_DIR/joint.docx" word/document.xml | grep -q '协办机关'
|
||||||
unzip -p "$TMP_DIR/joint.docx" word/document.xml | grep -q '文件'
|
unzip -p "$TMP_DIR/joint.docx" word/document.xml | grep -q '文件'
|
||||||
|
unzip -p "$TMP_DIR/joint.docx" word/document.xml | grep -q '主办机关 文件</w:t><w:br/>'
|
||||||
|
unzip -p "$TMP_DIR/joint.docx" word/document.xml | grep -q '协办机关</w:t>'
|
||||||
unzip -p "$TMP_DIR/joint.docx" word/document.xml | grep -q 'w:sz w:val="48"'
|
unzip -p "$TMP_DIR/joint.docx" word/document.xml | grep -q 'w:sz w:val="48"'
|
||||||
|
|
||||||
|
if "$NODE" "$GEN" --input "$FIXTURE" --output "$TMP_DIR/missing-joint-name.docx" --format formal --letterhead digital --org "主办机关文件" --joint-org --doc-no "示例发〔2026〕4号" --title "缺少联署机关名称" >"$TMP_DIR/missing-joint-name.out" 2>&1; then
|
||||||
|
echo "missing joint agency name unexpectedly succeeded" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
grep -q 'GENERATOR ERROR: --joint-org requires a value' "$TMP_DIR/missing-joint-name.out"
|
||||||
|
|
||||||
if "$NODE" "$GEN" --input "$FIXTURE" --output "$TMP_DIR/strict.docx" --format formal --letterhead digital --org "示例单位文件" --title "严格字体测试" --require-standard-fonts >"$TMP_DIR/strict.out" 2>&1; then
|
if "$NODE" "$GEN" --input "$FIXTURE" --output "$TMP_DIR/strict.docx" --format formal --letterhead digital --org "示例单位文件" --title "严格字体测试" --require-standard-fonts >"$TMP_DIR/strict.out" 2>&1; then
|
||||||
if ! fc-list -f '%{family}\n' | grep -Eq '方正小标宋简体|方正小标宋_GBK|FZXiaoBiaoSong'; then
|
if ! fc-list -f '%{family}\n' | grep -Eq '方正小标宋简体|方正小标宋_GBK|FZXiaoBiaoSong'; then
|
||||||
echo "strict font mode unexpectedly succeeded without a small-standard-title font" >&2
|
echo "strict font mode unexpectedly succeeded without a small-standard-title font" >&2
|
||||||
|
|||||||