线上运行 zb.demo.kinghtxg.com · Apache-2.0

把 Word 模板 变成一条产线

上传一份 docx 模板,交一批 JSON 数据。铸版负责渲染、转换 PDF、换图表数据、 盖签章、投递邮件,并把每一步写进不可篡改的审计链—— 一次几千份,样式一分不差。

模板与产物都不出你的服务器 三个容器跑起来
job / audit-report / 2026-Q3 running
template审计报告.docxv3.2 · 1 284 个槽位
records1 000校验通过 · 0 处缺失
formatdocx + pdf
charts12 张仅换数据,样式逐字节比对一致
render0342 / 1000并发 4
seal引用签章出图时打印签署时间
deliver邮件 1000 / 1000
zipdocx/ + pdf/两侧目录,解压即分层
signed直链 24hHMAC,可用不可猜
audit#00417已入哈希链
elapsed 00:41渲染中…
docx 1 000
pdf 1 000 · LibreOffice
投递 100%
一条链路

四个动作,从模板到成品

不需要写代码,也不需要拼 Office 自动化脚本。上传、填数、渲染、拿走—— 中间那些容易出错的活(版式漂移、字体缺失、图表错位、进度丢失、投递失败)由铸版接管。

① 上传模板

直接传你正在用的 .docx。扫描出全部变量槽位,标出必填项与类型。

扫描 · 变量识别

② 传数据

一份 JSON,或一批(数组)。先校验再渲染:缺字段当次就报,不会产出半成品。

校验 · 字段级报错

③ 异步渲染

任务进队列,逐条渲染、逐条记状态。失败了能单条重试,不会整批重来。

队列 · 断点续跑

④ 拿走成品

单个下载、打包 ZIP、签名直链,或直接发到收件人邮箱。每种方式都留审计。

ZIP · 直链 · 邮件
能力清单

容易被当成「Office 自动化脚本」的事,这里都做成了产品

下面九项里,有五项是真实项目里踩过坑才补上的(比如图表只换数据不动样式、 签章在现场出图、审计链可重算)。它们才是「能拿去生产用」和「能跑个 Demo」的区别。

变量渲染 Jinja2

底层是 docxtpl:{{ 变量 }}、循环、条件、过滤器全套可用。 变量能出现在正文、表格、页眉页脚、文本框里,不需要改造模板结构。

docxtpl · 槽位扫描 · 类型提示

批量与断点重试

一份数据是一份文档。任务按条记录状态,失败的单独重试, 已完成的不再重跑——5000 条跑到第 4000 条断网,不用从头再来。

任务队列 · 单条重试 · 进度可查

图表只换数据,不动样式

这是最容易做坏的一项:改图表数据时顺手把配色、字号、图例也改了。 铸版只重写 numCache/strCache,并用「剥掉数据节点后逐字节比对」 证明样式没动。

chart XML 双写 · style_fingerprint

签章在现场出图

传「引用签章 + 字体编号 + 时间表达式」,输出那一刻才生成带签署时间的签字图。 不是把一张旧图贴上去——签名与时间同源,审计时分得清。

$sig 引用 · 时间表达式 · 字体继承

在线编辑器

在浏览器里改模板本身:A4 画布按窗口自适应,块级选中、变量面板、 实时预览(依赖 LibreOffice)。改完立刻成为新版本,可回滚。

A4 画布 · 版本 · 回滚

邮件投递

SMTP 在服务端配置,收件人从数据里取。附件策略可选 docx / pdf / 两者 / 不附, 每封的回执状态都落库——投递是异步的,不能只看「接口没报错」。

附件策略 · 状态回执 · 域名白名单

API Key 与回调

给业务系统调用:API Key 带独立额度,任务完成回调可签名验真、可重放查询。 接入方不需要理解内部队列。

HMAC 签名 · 回调重放 · 额度控制

哈希链审计

谁在什么时候对哪份模板做了什么,一条一条串成哈希链。 可以全链重算验证——被改过一条,断点位置直接告诉你。

seq · prev_hash · 全链重算

归属隔离

任务 ID 是按日递增的,猜一个号就可能拿到别人的业务数据。 所以「能不能看到」按归属判定,非归属者一律 404(不是 403——403 等于承认它存在)。

任务 / 文档 / 直链 · 三条路径同口径
谁在用

凡是「同一个格式、填不同内容、要几千份」的活

这类工作的共同点是:模板是专家做的,内容是系统产的,量很大,错一份就要返工。 人肉填是最贵的方案。

01

安全审计报告

扫描器出结论,报告要按客户模板出。一家一份,还带整改建议和签章。

  • 图表随结果换数
  • 报告编号与日期自动填
  • 签章 + 签署时间
02

合规与备案文书

格式由监管定死,一个字都不能动,只能填。改错版式等于白做。

  • 版式零漂移
  • 必填项先校验
  • 批量子目录分包
03

合同与证书

几百份合同、几千张证书,甲乙方与金额各不同,出完还要发出去。

  • 一人一份 PDF
  • 邮件直投收件人
  • 投递状态可查
04

内部报表

周报月报季度报,数据在系统里,Word 模板在行政手里。

  • API 触发,无人值守
  • 定时批量跑
  • 失败单条重试
怎么搭的

Go 管业务,Python 管排版

渲染是 CPU 活、生态在 Python(docxtpl + LibreOffice);权限、队列、审计是业务活、 更适合 Go。两件事拆成两个服务,各自按需扩容,也各自能独立重启。

浏览器 Go API 认证 · 权限 · 审计 任务队列 逐条状态 · 断点重试 Python 渲染 docxtpl · LibreOffice docx / pdf 本地存储 · 签名直链 PostgreSQL APSSO / OIDC SMTP
渲染

docxtpl 负责内容,LibreOffice 负责换算

Jinja2 语义直接作用在 docx 的 XML 上,所以循环、条件、过滤器都能用; 转 PDF 交给无头 LibreOffice,避免「Word 里好看、服务器上跑版」。

顺序

图表数据必须在模板渲染之后写

docxtpl 会整包重写 docx,先改图表会被覆盖——表现是「参数传了但图没变」。 这类顺序问题没有报错,只能靠知道它存在来避开。

部署

三个容器,一条 compose

postgres / render / web。单机可跑,反代后只暴露一个端口; Docker 构建已切国内 apt 与 pip 源,LibreOffice 那层从 8 分钟降到 33 秒。

接入

复用你已有的身份体系

不自建账号中心:可接 APSSO(OIDC + PKCE)、可用本地账号, 也可以给业务系统发 API Key。三套入口,同一套权限模型。

0
自动化用例
go test + pytest
0
路由逐条验收匿名访问
遍历 chi 路由表
0
认证与队列包覆盖率
go tool cover 实测
0
容器跑起来
compose up -d
安全

输出的是带签章的正式文书,所以每条路径都得想清楚

下面这些不是「已实现的安全特性」清单,而是上线前逐条验过、并且写进了回归测试的判定标准。

四类对象都按归属判定

模板、任务、文档、签名直链。非归属者一律 404,避免用状态码反过来确认「这个 ID 存在」。

直链是 HMAC 签名,不是随机串

签名带有效期,可过期、可拒绝伪造。/s/<token> 本身就是凭证,不依赖登录态。

回调地址防 SSRF

默认拒绝私网与元数据地址(169.254.169.254 等),要开内网回调得显式配置白名单。

导出的 CSV 中和公式

审计日志里的显示名由用户可控,导出后被 Excel 打开可能执行公式。 所以以 = + - @ 开头的单元格会被加前缀中和。

登录失败按账号锁定

同一账号连续失败 5 次锁 5 分钟,锁定期间正确口令同样拒绝;同 IP 另有一层频次上限。

改密与禁号会立即失效会话

改密码踢掉其它设备、禁用账号撤销全部会话。 只清浏览器 cookie 的服务端会话仍然有效,所以必须撤服务端那一条。

开源

源码在 GitHub,Apache-2.0

整个服务都在这个仓库里:Go 主服务、Python 渲染服务、React 前端、 部署脚本与验收脚本。没有闭源模块,也没有「企业版才有」的功能开关。

github.com/kinghtxg/zhuban
许可Apache-2.0
主服务Go
渲染Python
前端React + TS
数据库PostgreSQL

下一批报告,让机器去填

装好就能用,先跑一份试试——不满意的地方,源码就在你手上。

已复制仓库地址