12 模板功能 - ZeroHawkeye/wordZero GitHub Wiki
模板功能实现教程
WordZero 提供了强大的模板引擎功能,支持动态内容生成、变量替换、条件渲染、循环处理等高级特性。本教程将详细介绍如何使用模板功能来创建动态文档。
目录
模板引擎概述
什么是模板引擎
模板引擎是WordZero提供的动态文档生成工具,它允许您:
- 动态内容替换:使用变量占位符动态替换文档内容
- 条件渲染:根据条件决定是否显示某些内容
- 循环处理:处理列表数据,自动生成重复内容
- 模板继承:基于基础模板创建扩展模板
- 结构体绑定:直接从Go结构体生成模板数据
支持的模板语法
语法 | 说明 | 示例 |
---|---|---|
{{变量名}} |
变量替换 | {{customerName}} |
{{#if 条件}}...{{/if}} |
条件语句 | {{#if isVip}}VIP内容{{/if}} |
{{#each 列表}}...{{/each}} |
循环语句 | {{#each items}}{{name}}{{/each}} |
{{#image 变量名}} |
图片占位符 | {{#image productImage}} |
{{extends "模板名"}} |
模板继承 | {{extends "base_template"}} |
{{#block "块名"}}...{{/block}} |
块定义/重写 | {{#block "content"}}内容{{/block}} |
{{this}} |
循环项当前值 | 在循环中使用 |
{{@index}} |
循环索引 | 0,1,2... |
{{@first}} |
是否第一项 | true/false |
{{@last}} |
是否最后一项 | true/false |
核心概念
1. TemplateEngine(模板引擎)
模板引擎是整个模板系统的核心,负责模板的加载、解析、缓存和渲染。
// 创建模板引擎
engine := document.NewTemplateEngine()
// 设置基础路径(可选)
engine.SetBasePath("templates/")
// 清空缓存
engine.ClearCache()
// 移除特定模板
engine.RemoveTemplate("template_name")
TemplateEngine 结构体字段:
cache
: 模板缓存映射表mutex
: 读写锁,保证并发安全basePath
: 模板基础路径
1.5. TemplateRenderer(模板渲染器)✨ 推荐使用
模板渲染器是对模板引擎的高级封装,提供了更友好的API和完善的日志功能。
// 创建模板渲染器(推荐方式)
renderer := document.NewTemplateRenderer()
// 设置日志记录
renderer.SetLogging(true) // 启用日志
renderer.SetLogging(false) // 禁用日志
TemplateRenderer 优势:
- 🔧 更简单的API: 封装了复杂的操作,提供简洁的接口
- 📝 完善的日志: 详细的操作日志,便于调试和监控
- 🛡️ 数据验证: 自动验证模板数据的完整性和格式
- 📊 模板分析: 提供模板结构分析功能
- 🚀 更好的错误处理: 友好的错误信息和上下文
何时使用 TemplateRenderer:
- ✅ 生产环境: 需要完善的日志和错误处理
- ✅ 复杂模板: 需要模板分析和数据验证功能
- ✅ 团队开发: 需要标准化的模板操作接口
- ✅ 调试阶段: 需要详细的日志信息
何时直接使用 TemplateEngine:
- ⚡ 性能优先: 对性能有极致要求的场景
- 🔧 精细控制: 需要直接控制底层模板引擎
- 📦 轻量级: 简单场景不需要额外的封装
2. Template(模板)
模板结构包含了模板的所有信息和配置。
type Template struct {
Name string // 模板名称
Content string // 模板内容
BaseDoc *Document // 基础文档
Variables map[string]string // 模板变量
Blocks []*TemplateBlock // 模板块
Parent *Template // 父模板(用于继承)
}
3. TemplateData(模板数据)
模板数据用于存储渲染时需要的所有数据。
type TemplateData struct {
Variables map[string]interface{} // 变量数据
Lists map[string][]interface{} // 列表数据
Conditions map[string]bool // 条件数据
}
4. TemplateBlock(模板块)
模板块表示模板中的结构化内容,如条件语句和循环语句。
type TemplateBlock struct {
Type string // 块类型:variable, if, each, inherit
Content string // 块内容
Condition string // 条件(if块使用)
Variable string // 变量名(each块使用)
Children []*TemplateBlock // 子块
Data map[string]interface{} // 块数据
}
5. TemplateAnalysis(模板分析结果)✨ 新增
模板分析结果包含了模板的结构信息和依赖关系。
type TemplateAnalysis struct {
TemplateName string // 模板名称
Variables map[string]bool // 变量列表
Lists map[string]bool // 列表变量
Conditions map[string]bool // 条件变量
Tables []*TableAnalysis // 表格分析
}
type TableAnalysis struct {
Index int // 表格索引
RowCount int // 行数
ColCount int // 列数
HasTemplate bool // 是否包含模板语法
TemplateRowIndex int // 模板行索引
TemplateVars map[string]bool // 模板变量
LoopVariables []string // 循环变量
}
基础功能
1. 创建和管理模板引擎
NewTemplateEngine()
创建新的模板引擎实例。
engine := document.NewTemplateEngine()
NewTemplateRenderer() ✨ 推荐
创建新的模板渲染器实例(推荐使用)。
renderer := document.NewTemplateRenderer()
SetBasePath(path string)
设置模板文件的基础路径。
engine.SetBasePath("/path/to/templates")
SetLogging(enabled bool) - TemplateRenderer
控制模板渲染器的日志记录功能。
renderer := document.NewTemplateRenderer()
renderer.SetLogging(true) // 启用详细日志
renderer.SetLogging(false) // 禁用日志(提升性能)
2. 加载模板
LoadTemplate(name, content string)
从字符串内容加载模板。
templateContent := `
Hello {{name}}!
Welcome to {{company}}.
`
template, err := engine.LoadTemplate("greeting", templateContent)
if err != nil {
log.Fatal(err)
}
LoadTemplateFromDocument(name string, doc *Document)
从现有文档创建模板。
// 创建一个基础文档
doc := document.New()
doc.AddParagraph("公司:{{companyName}}")
doc.AddParagraph("用户:{{userName}}")
// 从文档创建模板
template, err := engine.LoadTemplateFromDocument("user_doc", doc)
if err != nil {
log.Fatal(err)
}
LoadTemplateFromFile(name, filePath string) - TemplateRenderer ✨ 新增
从DOCX文件加载模板(仅在TemplateRenderer中可用)。
renderer := document.NewTemplateRenderer()
// 从现有的DOCX文件加载模板
template, err := renderer.LoadTemplateFromFile("invoice_template", "templates/invoice.docx")
if err != nil {
log.Fatal(err)
}
// 渲染器会自动记录加载过程
// [模板引擎] 成功加载模板: invoice_template (来源: templates/invoice.docx)
使用场景:
- 📄 现有DOCX文件: 将已有的Word文档转换为模板
- 🎨 设计师协作: 设计师提供DOCX模板,开发者直接使用
- 🔄 模板迁移: 从其他系统迁移现有模板文件
3. 模板数据操作
NewTemplateData()
创建新的模板数据实例。
data := document.NewTemplateData()
设置数据
// 设置单个变量
data.SetVariable("name", "张三")
data.SetVariable("age", 30)
// 批量设置变量
variables := map[string]interface{}{
"title": "欢迎文档",
"date": "2024-12-01",
}
data.SetVariables(variables)
// 设置列表数据
items := []interface{}{
map[string]interface{}{"name": "商品1", "price": 100},
map[string]interface{}{"name": "商品2", "price": 200},
}
data.SetList("products", items)
// 设置条件
data.SetCondition("isVip", true)
data.SetCondition("showDiscount", false)
获取数据
// 获取变量
value, exists := data.GetVariable("name")
if exists {
fmt.Printf("Name: %v\n", value)
}
// 获取列表
list, exists := data.GetList("products")
if exists {
fmt.Printf("Products count: %d\n", len(list))
}
// 获取条件
condition, exists := data.GetCondition("isVip")
if exists {
fmt.Printf("Is VIP: %v\n", condition)
}
4. 结构体数据绑定
FromStruct(data interface{})
从Go结构体自动生成模板数据。
type User struct {
Name string
Age int
Email string
IsActive bool
}
user := User{
Name: "李四",
Age: 25,
Email: "[email protected]",
IsActive: true,
}
templateData := document.NewTemplateData()
err := templateData.FromStruct(user)
if err != nil {
log.Fatal(err)
}
// 结构体字段名会被转换为小写作为变量名
// Name -> name, Age -> age, Email -> email, IsActive -> isactive
5. 渲染模板
RenderTemplate(templateName string, data *TemplateData) - TemplateRenderer ✨ 最推荐
使用模板渲染器渲染模板(最推荐的渲染方法)。
renderer := document.NewTemplateRenderer()
// 准备数据
data := document.NewTemplateData()
data.SetVariable("name", "王五")
data.SetVariable("company", "WordZero科技")
// 渲染模板(最推荐方法)
doc, err := renderer.RenderTemplate("greeting", data)
if err != nil {
log.Fatal(err)
}
// 保存文档
err = doc.Save("output/rendered_document.docx")
自动日志记录:
[模板引擎] 开始渲染模板: greeting
[模板引擎] 模板数据统计: 变量=2, 列表=0, 条件=0
[模板引擎] 模板渲染完成: greeting
RenderTemplateToDocument(templateName string, data *TemplateData) ✨ 推荐方法
将模板渲染为Word文档(主要渲染方法,支持基于基础文档的直接结构化替换)。
这是推荐使用的主要渲染方法,相比 RenderToDocument
,该方法提供了更好的性能和格式保持能力:
// 准备数据
data := document.NewTemplateData()
data.SetVariable("name", "王五")
data.SetVariable("company", "WordZero科技")
// 渲染模板(推荐方法)
doc, err := engine.RenderTemplateToDocument("greeting", data)
if err != nil {
log.Fatal(err)
}
// 保存文档
err = doc.Save("output/rendered_document.docx")
if err != nil {
log.Fatal(err)
}
RenderTemplateToDocument 优势:
- 🚀 更好性能: 基于基础文档进行直接结构化替换,避免字符串解析开销
- 🎯 更好格式保持: 完整保留基础文档的所有格式、样式和结构
- 💪 更强兼容性: 支持复杂文档结构,包括表格、图片、样式等
- 🔧 更好扩展性: 为未来高级功能提供更好的基础架构
RenderToDocument(templateName string, data *TemplateData)
将模板渲染为Word文档(传统方法,适用于纯文本模板)。
此方法适用于简单的文本模板或没有基础文档的模板:
// 准备数据
data := document.NewTemplateData()
data.SetVariable("name", "王五")
data.SetVariable("company", "WordZero科技")
// 渲染模板(传统方法)
doc, err := engine.RenderToDocument("greeting", data)
if err != nil {
log.Fatal(err)
}
// 保存文档
err = doc.Save("output/rendered_document.docx")
if err != nil {
log.Fatal(err)
}
方法选择指南:
- 🏆 首选: 使用
TemplateRenderer.RenderTemplate()
(推荐) - 📄 有基础文档模板: 优先使用
RenderTemplateToDocument
- 📝 纯文本模板: 可使用
RenderToDocument
- 🎨 复杂格式要求: 建议使用
RenderTemplateToDocument
- ⚡ 性能要求高: 推荐使用
RenderTemplateToDocument
6. 模板分析功能 ✨ 新增
AnalyzeTemplate(templateName string) - TemplateRenderer
分析模板结构,获取模板中使用的变量、列表、条件等信息。
renderer := document.NewTemplateRenderer()
// 加载模板
renderer.LoadTemplateFromFile("complex_template", "templates/report.docx")
// 分析模板结构
analysis, err := renderer.AnalyzeTemplate("complex_template")
if err != nil {
log.Fatal(err)
}
// 获取分析结果
fmt.Printf("模板名称: %s\n", analysis.TemplateName)
fmt.Printf("变量数量: %d\n", len(analysis.Variables))
fmt.Printf("列表数量: %d\n", len(analysis.Lists))
fmt.Printf("条件数量: %d\n", len(analysis.Conditions))
fmt.Printf("表格数量: %d\n", len(analysis.Tables))
// 查看变量列表
fmt.Println("模板变量:")
for varName := range analysis.Variables {
fmt.Printf(" - {{%s}}\n", varName)
}
// 查看条件列表
fmt.Println("条件变量:")
for condName := range analysis.Conditions {
fmt.Printf(" - {{#if %s}}\n", condName)
}
// 查看列表变量
fmt.Println("循环列表:")
for listName := range analysis.Lists {
fmt.Printf(" - {{#each %s}}\n", listName)
}
自动日志记录:
[模板引擎] 模板分析完成: complex_template
[模板引擎] - 变量: 8
[模板引擎] - 列表: 2
[模板引擎] - 条件: 3
[模板引擎] - 表格: 1
GetRequiredData() - TemplateAnalysis
根据模板分析结果生成示例数据结构。
// 分析模板
analysis, _ := renderer.AnalyzeTemplate("complex_template")
// 生成示例数据
sampleData := analysis.GetRequiredData()
// 可以基于示例数据创建真实数据
realData := document.NewTemplateData()
realData.SetVariable("customerName", "真实客户名")
realData.SetVariable("orderDate", "2024-12-01")
// ... 设置其他数据
使用场景:
- 🔍 模板调试: 了解模板结构和依赖
- 📝 文档生成: 自动生成模板使用说明
- 🧪 测试数据: 生成模板测试所需的示例数据
- 🔧 模板验证: 检查模板的完整性和正确性
高级功能
1. 变量替换
基础的变量替换使用 {{变量名}}
语法。
templateContent := `
客户信息
姓名:{{customerName}}
电话:{{phone}}
邮箱:{{email}}
注册日期:{{registerDate}}
`
data := document.NewTemplateData()
data.SetVariable("customerName", "赵六")
data.SetVariable("phone", "138-0000-0000")
data.SetVariable("email", "[email protected]")
data.SetVariable("registerDate", "2024-12-01")
2. 条件语句
使用 {{#if 条件}}...{{/if}}
语法实现条件渲染。
templateContent := `
用户报告
基本信息:
用户名:{{username}}
{{#if isPremium}}
🎖️ 尊贵的高级会员
您享有以下特权:
- 无限下载
- 优先客服支持
- 专属活动邀请
{{/if}}
{{#if hasUnreadMessages}}
📧 您有 {{unreadCount}} 条未读消息
{{/if}}
{{#if needRenewal}}
⚠️ 您的会员即将到期,请及时续费
{{/if}}
`
data := document.NewTemplateData()
data.SetVariable("username", "高级用户")
data.SetVariable("unreadCount", 5)
data.SetCondition("isPremium", true)
data.SetCondition("hasUnreadMessages", true)
data.SetCondition("needRenewal", false)
3. 循环语句
使用 {{#each 列表名}}...{{/each}}
语法处理列表数据。
templateContent := `
销售报告
产品销售明细:
{{#each products}}
{{@index}}. 产品名称:{{name}}
销售数量:{{quantity}} 件
单价:{{price}} 元
总金额:{{total}} 元
{{#if isPopular}}⭐ 热销商品{{/if}}
{{/each}}
总计:{{grandTotal}} 元
`
// 准备产品数据
products := []interface{}{
map[string]interface{}{
"name": "WordZero专业版",
"quantity": 150,
"price": 299.00,
"total": 44850.00,
"isPopular": true,
},
map[string]interface{}{
"name": "WordZero标准版",
"quantity": 200,
"price": 199.00,
"total": 39800.00,
"isPopular": false,
},
}
data := document.NewTemplateData()
data.SetList("products", products)
data.SetVariable("grandTotal", 84650.00)
4. 循环上下文变量
在循环中可以使用特殊的上下文变量:
{{this}}
: 当前循环项的值(如果是简单类型){{@index}}
: 当前项的索引(从0开始){{@first}}
: 是否是第一项(true/false){{@last}}
: 是否是最后一项(true/false)
templateContent := `
团队成员列表:
{{#each members}}
{{#if @first}}=== 团队成员 ===
{{/if}}
{{@index}}. {{name}} - {{position}}
{{#if @last}}
=== 共 {{@index}} 人 ===
{{/if}}
{{/each}}
`
5. 模板继承 ✨ 新增块重写机制
使用 {{extends "基础模板名"}}
语法实现模板继承,支持块定义和重写功能。
块定义语法
// 基础模板:定义可重写的块
baseTemplate := `{{companyName}} 官方文档
{{#block "header"}}
标题:{{title}}
版本:{{version}}
创建时间:{{createTime}}
{{/block}}
{{#block "content"}}
默认内容区域
这里是默认的文档内容。
{{/block}}
{{#block "footer"}}
版权所有 © {{year}} {{companyName}}
{{/block}}`
engine.LoadTemplate("base_doc", baseTemplate)
块重写语法
// 子模板:继承基础模板并重写特定块
childTemplate := `{{extends "base_doc"}}
{{#block "content"}}
用户手册内容
第一章:快速开始
欢迎使用我们的产品!这里是详细的使用说明...
第二章:高级功能
高级功能包括:
- 模板系统
- 批量处理
- API集成
{{/block}}
{{#block "footer"}}
技术支持:[email protected]
版权所有 © {{year}} {{companyName}}
{{/block}}`
engine.LoadTemplate("user_manual", childTemplate)
多级继承
// 第一级:基础文档
baseDocTemplate := `{{#block "document_header"}}文档{{/block}}
{{#block "body"}}内容{{/block}}
{{#block "document_footer"}}页脚{{/block}}`
// 第二级:技术文档
techDocTemplate := `{{extends "base_doc"}}
{{#block "body"}}
{{#block "overview"}}概述{{/block}}
{{#block "details"}}详情{{/block}}
{{/block}}`
// 第三级:API文档
apiDocTemplate := `{{extends "tech_doc"}}
{{#block "overview"}}API概述{{/block}}
{{#block "details"}}API详情{{/block}}`
块默认内容保留
// 如果子模板没有重写某个块,将使用父模板的默认内容
parentTemplate := `{{#block "header"}}默认标题{{/block}}
{{#block "content"}}默认内容{{/block}}
{{#block "footer"}}默认页脚{{/block}}`
childTemplate := `{{extends "parent"}}
{{#block "content"}}自定义内容{{/block}}`
// header和footer块将保持父模板的默认内容
### 6. 图片占位符 ✨ **新增特性**
使用 `{{#image 变量名}}` 语法在模板中插入图片占位符。
#### 基础图片占位符语法
```go
templateContent := `
产品介绍文档
产品名称:{{productName}}
产品图片:
{{#image productImage}}
产品描述:{{productDescription}}
价格:{{price}}
`
// 创建模板引擎
engine := document.NewTemplateEngine()
engine.LoadTemplate("product_intro", templateContent)
// 准备数据
data := document.NewTemplateData()
data.SetVariable("productName", "智能手表 Pro")
data.SetVariable("productDescription", "功能强大的智能手表")
data.SetVariable("price", "¥1,299")
// 配置图片样式
imageConfig := &document.ImageConfig{
Position: document.ImagePositionInline,
Alignment: document.AlignCenter,
Size: &document.ImageSize{
Width: 100, // 宽度100mm
KeepAspectRatio: true,
},
AltText: "产品图片",
Title: "智能手表 Pro",
}
// 设置图片数据(支持二进制数据)
imageData := loadImageFromFile("product.png") // 你的图片加载函数
data.SetImageFromData("productImage", imageData, imageConfig)
// 渲染模板
doc, _ := engine.RenderToDocument("product_intro", data)
doc.Save("product_intro.docx")
图片配置选项
// 完整的图片配置示例
imageConfig := &document.ImageConfig{
// 图片位置
Position: document.ImagePositionInline, // 内联(默认)| 左浮动 | 右浮动
// 对齐方式(用于内联图片)
Alignment: document.AlignCenter, // 左对齐 | 居中 | 右对齐
// 图片大小
Size: &document.ImageSize{
Width: 80, // 宽度(毫米)
Height: 60, // 高度(毫米)
KeepAspectRatio: true, // 保持长宽比
},
// 文字环绕
WrapText: document.ImageWrapSquare, // 无环绕 | 四周环绕 | 紧密环绕 | 上下环绕
// 图片描述
AltText: "产品展示图片",
Title: "智能手表展示",
// 偏移量(毫米)
OffsetX: 5.0, // 水平偏移
OffsetY: 3.0, // 垂直偏移
}
多图片模板示例
templateContent := `
安装指南:{{title}}
步骤1:{{step1Description}}
{{#image step1Image}}
步骤2:{{step2Description}}
{{#image step2Image}}
步骤3:{{step3Description}}
{{#image step3Image}}
完成安装!
`
data := document.NewTemplateData()
data.SetVariable("title", "设备安装指南")
data.SetVariable("step1Description", "打开包装,取出所有组件")
data.SetVariable("step2Description", "连接电源线")
data.SetVariable("step3Description", "启动设备")
// 为每个步骤配置不同的图片
stepImageConfig := &document.ImageConfig{
Position: document.ImagePositionInline,
Alignment: document.AlignCenter,
Size: &document.ImageSize{
Width: 70,
KeepAspectRatio: true,
},
}
// 设置多个图片
step1ImageData := loadImageFromFile("step1.png")
step2ImageData := loadImageFromFile("step2.png")
step3ImageData := loadImageFromFile("step3.png")
data.SetImageFromData("step1Image", step1ImageData, stepImageConfig)
data.SetImageFromData("step2Image", step2ImageData, stepImageConfig)
data.SetImageFromData("step3Image", step3ImageData, stepImageConfig)
doc, _ := engine.RenderToDocument("install_guide", data)
从现有文档创建图片模板
// 创建包含图片占位符的基础文档
baseDoc := document.New()
baseDoc.AddParagraph("{{companyName}} 产品目录")
baseDoc.AddParagraph("产品名称:{{productName}}")
baseDoc.AddParagraph("{{#image productImage}}")
baseDoc.AddParagraph("价格:{{price}}")
// 从文档创建模板
engine := document.NewTemplateEngine()
template, _ := engine.LoadTemplateFromDocument("catalog", baseDoc)
// 准备数据和图片
data := document.NewTemplateData()
data.SetVariable("companyName", "创新科技")
data.SetVariable("productName", "智能音箱")
data.SetVariable("price", "¥299")
imageConfig := &document.ImageConfig{
Position: document.ImagePositionInline,
Alignment: document.AlignCenter,
Size: &document.ImageSize{
Width: 90,
KeepAspectRatio: true,
},
}
imageData := loadImageFromFile("speaker.png")
data.SetImageFromData("productImage", imageData, imageConfig)
doc, _ := engine.RenderTemplateToDocument("catalog", data)
支持的图片格式
WordZero支持以下图片格式:
- JPEG (.jpg, .jpeg)
- PNG (.png) - 支持透明背景
- GIF (.gif) - 支持动画
图片处理最佳实践
// ✅ 推荐:合理的图片尺寸
imageConfig := &document.ImageConfig{
Size: &document.ImageSize{
Width: 100, // 适中的宽度
KeepAspectRatio: true, // 保持长宽比
},
}
// ✅ 推荐:设置替代文本和标题
imageConfig.AltText = "产品展示图片"
imageConfig.Title = "智能设备产品图"
// ✅ 推荐:根据内容选择合适的对齐方式
imageConfig.Alignment = document.AlignCenter // 产品图片居中
// imageConfig.Alignment = document.AlignLeft // 步骤图片左对齐
// ❌ 避免:过大的图片尺寸
imageConfig.Size.Width = 300 // 可能导致页面布局问题
// ❌ 避免:忘记设置替代文本
// 缺少 AltText 会影响文档的可访问性
7. 复杂数据结构处理
模板引擎支持复杂的嵌套数据结构。
templateContent := `
项目报告
项目基本信息:
项目名称:{{projectName}}
项目经理:{{managerName}}
团队结构:
{{#each departments}}
部门:{{name}}
负责人:{{manager}}
成员数量:{{memberCount}}
主要成员:
{{#each members}}
- {{name}} ({{position}})
{{#if isLead}}👨💼 部门主管{{/if}}
{{/each}}
{{#if hasAchievements}}
部门成就:
{{#each achievements}}
✅ {{this}}
{{/each}}
{{/if}}
{{/each}}
`
// 准备复杂数据
departments := []interface{}{
map[string]interface{}{
"name": "开发部",
"manager": "张技术",
"memberCount": 8,
"hasAchievements": true,
"achievements": []interface{}{
"完成核心模块开发",
"提升系统性能50%",
},
"members": []interface{}{
map[string]interface{}{
"name": "李开发",
"position": "高级工程师",
"isLead": true,
},
map[string]interface{}{
"name": "王程序",
"position": "工程师",
"isLead": false,
},
},
},
}
data := document.NewTemplateData()
data.SetList("departments", departments)
实际应用示例
1. 商业发票模板
func generateInvoice() {
engine := document.NewTemplateEngine()
invoiceTemplate := `
发票
发票号码:{{invoiceNumber}}
开票日期:{{issueDate}}
付款期限:{{dueDate}}
开票方:
{{sellerName}}
{{sellerAddress}}
电话:{{sellerPhone}}
邮箱:{{sellerEmail}}
收票方:
{{buyerName}}
{{buyerAddress}}
电话:{{buyerPhone}}
商品明细:
{{#each items}}
{{@index}}. {{description}}
数量:{{quantity}} {{unit}}
单价:{{unitPrice}} 元
小计:{{subtotal}} 元
{{/each}}
{{#if hasDiscount}}
折扣:-{{discount}} 元
{{/if}}
{{#if hasTax}}
税费:{{tax}} 元
{{/if}}
总计:{{total}} 元
{{#if isPaid}}
✅ 已付款
{{/if}}
{{#if isOverdue}}
⚠️ 已逾期
{{/if}}
`
engine.LoadTemplate("invoice", invoiceTemplate)
// 准备发票数据
data := document.NewTemplateData()
data.SetVariable("invoiceNumber", "INV-2024-001")
data.SetVariable("issueDate", "2024-12-01")
data.SetVariable("dueDate", "2024-12-31")
// 发票方信息
data.SetVariable("sellerName", "WordZero科技有限公司")
data.SetVariable("sellerAddress", "上海市浦东新区科技园区1号楼")
data.SetVariable("sellerPhone", "021-12345678")
data.SetVariable("sellerEmail", "[email protected]")
// 收票方信息
data.SetVariable("buyerName", "客户公司")
data.SetVariable("buyerAddress", "北京市朝阳区商务楼A座")
data.SetVariable("buyerPhone", "010-87654321")
// 商品明细
items := []interface{}{
map[string]interface{}{
"description": "WordZero专业版授权",
"quantity": 1,
"unit": "套",
"unitPrice": 2999.00,
"subtotal": 2999.00,
},
map[string]interface{}{
"description": "技术支持服务",
"quantity": 12,
"unit": "月",
"unitPrice": 500.00,
"subtotal": 6000.00,
},
}
data.SetList("items", items)
// 其他信息
data.SetVariable("discount", 200.00)
data.SetVariable("tax", 719.88)
data.SetVariable("total", 9518.88)
data.SetCondition("hasDiscount", true)
data.SetCondition("hasTax", true)
data.SetCondition("isPaid", false)
data.SetCondition("isOverdue", false)
// 渲染并保存
doc, _ := engine.RenderTemplateToDocument("invoice", data)
doc.Save("invoice.docx")
}
2. 员工绩效报告
func generatePerformanceReport() {
engine := document.NewTemplateEngine()
reportTemplate := `
员工绩效报告
报告期间:{{reportPeriod}}
评估日期:{{evaluationDate}}
员工信息:
姓名:{{employeeName}}
工号:{{employeeId}}
部门:{{department}}
职位:{{position}}
直属上级:{{supervisor}}
绩效评分:
{{#each categories}}
{{name}}:{{score}}/10
{{#if hasComment}}
评语:{{comment}}
{{/if}}
{{/each}}
总体评分:{{overallScore}}/10
{{#if hasAchievements}}
主要成就:
{{#each achievements}}
✅ {{this}}
{{/each}}
{{/if}}
{{#if hasImprovements}}
改进建议:
{{#each improvements}}
📝 {{this}}
{{/each}}
{{/if}}
{{#if isPromotionRecommended}}
🎉 推荐晋升
{{/if}}
{{#if needsTraining}}
📚 建议参加培训
{{/if}}
评估人:{{evaluator}}
评估人签名:________________
日期:{{signDate}}
`
engine.LoadTemplate("performance", reportTemplate)
// 使用结构体准备数据
type PerformanceCategory struct {
Name string
Score int
HasComment bool
Comment string
}
type Employee struct {
Name string
Id string
Department string
Position string
Supervisor string
}
employee := Employee{
Name: "张工程师",
Id: "EMP001",
Department: "技术部",
Position: "高级软件工程师",
Supervisor: "李经理",
}
data := document.NewTemplateData()
data.FromStruct(employee)
// 其他数据
data.SetVariable("reportPeriod", "2024年第四季度")
data.SetVariable("evaluationDate", "2024-12-01")
data.SetVariable("overallScore", 8)
data.SetVariable("evaluator", "李经理")
data.SetVariable("signDate", "2024-12-01")
// 绩效类别
categories := []interface{}{
map[string]interface{}{
"name": "工作质量",
"score": 9,
"hasComment": true,
"comment": "代码质量高,bug率低",
},
map[string]interface{}{
"name": "工作效率",
"score": 8,
"hasComment": false,
},
map[string]interface{}{
"name": "团队协作",
"score": 8,
"hasComment": true,
"comment": "积极参与团队讨论,乐于助人",
},
}
data.SetList("categories", categories)
// 成就和改进建议
achievements := []interface{}{
"完成了核心模块的重构",
"主导了新功能的技术方案设计",
"帮助团队解决了多个技术难题",
}
data.SetList("achievements", achievements)
improvements := []interface{}{
"可以加强项目管理能力",
"建议学习新的技术栈",
}
data.SetList("improvements", improvements)
data.SetCondition("hasAchievements", true)
data.SetCondition("hasImprovements", true)
data.SetCondition("isPromotionRecommended", true)
data.SetCondition("needsTraining", false)
// 渲染并保存
doc, _ := engine.RenderTemplateToDocument("performance", data)
doc.Save("performance_report.docx")
}
3. 会议记录模板
func generateMeetingMinutes() {
engine := document.NewTemplateEngine()
minutesTemplate := `
会议记录
会议主题:{{meetingTitle}}
会议时间:{{meetingDate}} {{meetingTime}}
会议地点:{{location}}
主持人:{{chairperson}}
记录人:{{recorder}}
出席人员:
{{#each attendees}}
• {{name}} - {{department}} - {{title}}
{{#if isRequired}}
📌 必须参会
{{/if}}
{{#if isAbsent}}
❌ 缺席(原因:{{absentReason}})
{{/if}}
{{/each}}
会议议程:
{{#each agendaItems}}
{{@index}}. {{topic}}
负责人:{{owner}}
{{#if hasDiscussion}}
讨论要点:
{{#each discussionPoints}}
- {{this}}
{{/each}}
{{/if}}
{{#if hasDecision}}
决议:{{decision}}
{{/if}}
{{#if hasActionItems}}
行动项:
{{#each actionItems}}
✓ {{task}} - 负责人:{{assignee}} - 截止日期:{{dueDate}}
{{/each}}
{{/if}}
{{/each}}
会议总结:
{{#if hasSummary}}
{{summary}}
{{/if}}
下次会议:
{{#if hasNextMeeting}}
时间:{{nextMeetingDate}}
议题:{{nextMeetingAgenda}}
{{/if}}
记录人签名:________________
主持人确认:________________
日期:{{signDate}}
`
engine.LoadTemplate("meeting_minutes", minutesTemplate)
// 准备会议数据
data := document.NewTemplateData()
data.SetVariable("meetingTitle", "产品规划季度会议")
data.SetVariable("meetingDate", "2024年12月15日")
data.SetVariable("meetingTime", "14:00-16:00")
data.SetVariable("location", "会议室A301")
data.SetVariable("chairperson", "张总经理")
data.SetVariable("recorder", "李秘书")
// 出席人员
attendees := []interface{}{
map[string]interface{}{
"name": "王产品经理",
"department": "产品部",
"title": "产品经理",
"isRequired": true,
"isAbsent": false,
},
map[string]interface{}{
"name": "刘技术总监",
"department": "技术部",
"title": "技术总监",
"isRequired": true,
"isAbsent": false,
},
map[string]interface{}{
"name": "陈市场主管",
"department": "市场部",
"title": "市场主管",
"isRequired": false,
"isAbsent": true,
"absentReason": "出差",
},
}
data.SetList("attendees", attendees)
// 会议议程
agendaItems := []interface{}{
map[string]interface{}{
"topic": "2025年产品发展战略",
"owner": "王产品经理",
"hasDiscussion": true,
"discussionPoints": []interface{}{
"确定三个核心产品方向",
"评估市场竞争态势",
"制定差异化策略",
},
"hasDecision": true,
"decision": "专注于企业级文档处理解决方案",
"hasActionItems": true,
"actionItems": []interface{}{
map[string]interface{}{
"task": "完成竞品分析报告",
"assignee": "王产品经理",
"dueDate": "2024年12月30日",
},
map[string]interface{}{
"task": "制定技术路线图",
"assignee": "刘技术总监",
"dueDate": "2025年01月15日",
},
},
},
map[string]interface{}{
"topic": "用户反馈分析",
"owner": "李用户研究员",
"hasDiscussion": true,
"discussionPoints": []interface{}{
"用户满意度达到85%",
"主要改进需求集中在性能优化",
"新功能需求以模板功能为主",
},
"hasDecision": false,
"hasActionItems": true,
"actionItems": []interface{}{
map[string]interface{}{
"task": "优化核心功能性能",
"assignee": "技术团队",
"dueDate": "2025年02月01日",
},
},
},
}
data.SetList("agendaItems", agendaItems)
// 其他信息
data.SetVariable("summary", "会议确定了2025年产品发展方向,各部门需要在规定时间内完成相应的行动项。")
data.SetVariable("nextMeetingDate", "2025年01月15日")
data.SetVariable("nextMeetingAgenda", "产品开发进度汇报")
data.SetVariable("signDate", "2024年12月15日")
data.SetCondition("hasSummary", true)
data.SetCondition("hasNextMeeting", true)
// 渲染并保存
doc, _ := engine.RenderTemplateToDocument("meeting_minutes", data)
doc.Save("meeting_minutes.docx")
}
4. 学生成绩单模板
func generateStudentReport() {
engine := document.NewTemplateEngine()
reportTemplate := `
学生成绩报告单
学生信息:
姓名:{{studentName}}
学号:{{studentId}}
班级:{{className}}
学期:{{semester}}
评估日期:{{reportDate}}
成绩概览:
总平均分:{{overallAverage}}
年级排名:{{classRank}}/{{totalStudents}}
学分:{{totalCredits}}
课程成绩明细:
{{#each subjects}}
{{name}} ({{credits}}学分)
平时成绩:{{regularScore}} | 期中成绩:{{midtermScore}} | 期末成绩:{{finalScore}}
综合成绩:{{totalScore}} | 等级:{{grade}}
{{#if isPassed}}
✓ 通过
{{/if}}
{{#if needsImprovement}}
⚠️ 需要改进
{{/if}}
{{/each}}
学科能力分析:
{{#each skillAreas}}
{{area}}:{{level}}
{{#if hasComment}}
评语:{{comment}}
{{/if}}
{{/each}}
出勤情况:
应到课时:{{expectedHours}} 小时
实际出勤:{{actualHours}} 小时
出勤率:{{attendanceRate}}%
{{#if hasAbsences}}
缺勤记录:
{{#each absences}}
日期:{{date}} | 课程:{{subject}} | 原因:{{reason}}
{{/each}}
{{/if}}
综合评价:
{{#if isExcellent}}
🏆 优秀学生
{{/if}}
{{#if needsSupport}}
📚 建议加强学习支持
{{/if}}
家长意见:
{{#if hasParentFeedback}}
{{parentFeedback}}
家长签名:________________
{{/if}}
班主任评语:
{{teacherComment}}
班主任:{{teacherName}}
签名:________________
日期:{{signDate}}
`
engine.LoadTemplate("student_report", reportTemplate)
// 使用结构体定义学生数据
type Subject struct {
Name string
Credits int
RegularScore int
MidtermScore int
FinalScore int
TotalScore int
Grade string
IsPassed bool
NeedsImprovement bool
}
// 准备成绩数据
data := document.NewTemplateData()
data.SetVariable("studentName", "李明")
data.SetVariable("studentId", "2024001")
data.SetVariable("className", "软件工程2024级1班")
data.SetVariable("semester", "2024-2025学年第一学期")
data.SetVariable("reportDate", "2024年12月20日")
data.SetVariable("overallAverage", 87.5)
data.SetVariable("classRank", 8)
data.SetVariable("totalStudents", 45)
data.SetVariable("totalCredits", 22)
// 课程成绩
subjects := []interface{}{
map[string]interface{}{
"name": "高等数学",
"credits": 4,
"regularScore": 85,
"midtermScore": 88,
"finalScore": 90,
"totalScore": 88,
"grade": "B+",
"isPassed": true,
"needsImprovement": false,
},
map[string]interface{}{
"name": "程序设计基础",
"credits": 4,
"regularScore": 92,
"midtermScore": 95,
"finalScore": 93,
"totalScore": 93,
"grade": "A",
"isPassed": true,
"needsImprovement": false,
},
map[string]interface{}{
"name": "英语",
"credits": 3,
"regularScore": 75,
"midtermScore": 78,
"finalScore": 80,
"totalScore": 78,
"grade": "C+",
"isPassed": true,
"needsImprovement": true,
},
}
data.SetList("subjects", subjects)
// 学科能力分析
skillAreas := []interface{}{
map[string]interface{}{
"area": "逻辑思维",
"level": "优秀",
"hasComment": true,
"comment": "数学建模能力强,思路清晰",
},
map[string]interface{}{
"area": "编程能力",
"level": "优秀",
"hasComment": true,
"comment": "代码规范,算法理解深入",
},
map[string]interface{}{
"area": "语言表达",
"level": "良好",
"hasComment": true,
"comment": "建议加强英语听说练习",
},
}
data.SetList("skillAreas", skillAreas)
// 出勤情况
data.SetVariable("expectedHours", 320)
data.SetVariable("actualHours", 312)
data.SetVariable("attendanceRate", 97.5)
absences := []interface{}{
map[string]interface{}{
"date": "2024-11-15",
"subject": "英语",
"reason": "感冒请假",
},
map[string]interface{}{
"date": "2024-12-03",
"subject": "高等数学",
"reason": "家庭事务",
},
}
data.SetList("absences", absences)
// 其他信息
data.SetVariable("parentFeedback", "孩子学习态度端正,希望能在英语方面多下功夫。")
data.SetVariable("teacherComment", "李明同学学习认真,思维活跃,是班级的学习榜样。建议在英语学习上投入更多时间,相信会有更大进步。")
data.SetVariable("teacherName", "王老师")
data.SetVariable("signDate", "2024年12月20日")
data.SetCondition("isExcellent", true)
data.SetCondition("needsSupport", false)
data.SetCondition("hasAbsences", true)
data.SetCondition("hasParentFeedback", true)
// 渲染并保存
doc, _ := engine.RenderTemplateToDocument("student_report", data)
doc.Save("student_report.docx")
}
5. 从现有DOCX模板生成文档
基于我们之前实现的功能,演示如何使用现有的Word模板文件:
func generateFromExistingTemplate() {
fmt.Println("=== 从现有DOCX模板生成文档演示 ===")
// 1. 创建模板引擎
engine := document.NewTemplateEngine()
// 2. 打开现有的DOCX模板文件
templateDoc, err := document.Open("templates/contract_template.docx")
if err != nil {
log.Fatalf("无法打开模板文件: %v", err)
}
fmt.Println("✓ 成功打开模板文件")
// 3. 从文档创建模板
template, err := engine.LoadTemplateFromDocument("contract_template", templateDoc)
if err != nil {
log.Fatalf("从文档创建模板失败: %v", err)
}
fmt.Printf("✓ 解析到 %d 个模板变量\n", len(template.Variables))
// 4. 准备合同数据
data := document.NewTemplateData()
// 基本信息
data.SetVariable("contractNumber", "CONTRACT-2024-001")
data.SetVariable("signDate", time.Now().Format("2006年01月02日"))
data.SetVariable("effectiveDate", time.Now().Format("2006年01月02日"))
data.SetVariable("expirationDate", time.Now().AddDate(1, 0, 0).Format("2006年01月02日"))
// 甲方信息
data.SetVariable("partyAName", "WordZero科技有限公司")
data.SetVariable("partyAAddress", "上海市浦东新区科技园区1号楼")
data.SetVariable("partyALegal", "张总经理")
data.SetVariable("partyAPhone", "021-12345678")
// 乙方信息
data.SetVariable("partyBName", "客户企业有限公司")
data.SetVariable("partyBAddress", "北京市朝阳区商务楼A座")
data.SetVariable("partyBLegal", "李总经理")
data.SetVariable("partyBPhone", "010-87654321")
// 合同条款
clauses := []interface{}{
map[string]interface{}{
"title": "服务内容",
"content": "甲方向乙方提供WordZero企业版软件授权及相关技术支持服务。",
},
map[string]interface{}{
"title": "服务期限",
"content": "本合同服务期限为一年,自签署之日起生效。",
},
map[string]interface{}{
"title": "费用条款",
"content": "乙方应向甲方支付服务费用总计人民币50,000元整。",
},
}
data.SetList("clauses", clauses)
// 付款计划
payments := []interface{}{
map[string]interface{}{
"phase": "签约时",
"amount": "25,000",
"percentage": "50%",
"dueDate": "合同签署当日",
},
map[string]interface{}{
"phase": "服务中期",
"amount": "15,000",
"percentage": "30%",
"dueDate": "服务开始后6个月",
},
map[string]interface{}{
"phase": "服务完成",
"amount": "10,000",
"percentage": "20%",
"dueDate": "服务验收后10个工作日",
},
}
data.SetList("payments", payments)
// 条件设置
data.SetCondition("hasSpecialTerms", true)
data.SetCondition("needsApproval", false)
data.SetCondition("hasAttachments", true)
// 5. 渲染生成合同
contractDoc, err := engine.RenderTemplateToDocument("contract_template", data)
if err != nil {
log.Fatalf("渲染合同失败: %v", err)
}
// 6. 保存生成的合同
outputFile := "output/generated_contract_" + time.Now().Format("20060102_150405") + ".docx"
err = contractDoc.Save(outputFile)
if err != nil {
log.Fatalf("保存合同失败: %v", err)
}
fmt.Printf("✓ 成功生成合同文档: %s\n", outputFile)
}
6. 产品目录图片模板 ✨ 图片占位符实例
func generateProductCatalogWithImages() {
fmt.Println("=== 产品目录图片模板演示 ===")
engine := document.NewTemplateEngine()
catalogTemplate := `{{companyName}} 产品目录 2024
欢迎浏览我们的最新产品系列!
{{#each products}}
产品 {{@index}}:{{name}}
产品图片:
{{#image productImage}}
产品信息:
- 型号:{{model}}
- 价格:{{price}}
- 库存状态:{{#if inStock}}✅ 有库存{{/if}}{{#unless inStock}}❌ 暂时缺货{{/unless}}
产品特色:
{{#each features}}
• {{this}}
{{/each}}
{{#if hasPromotion}}
🎉 特别优惠:{{promotionText}}
{{/if}}
---
{{/each}}
联系我们:
电话:{{contactPhone}}
邮箱:{{contactEmail}}
地址:{{contactAddress}}
`
engine.LoadTemplate("product_catalog", catalogTemplate)
// 准备产品数据
data := document.NewTemplateData()
data.SetVariable("companyName", "创新科技")
data.SetVariable("contactPhone", "400-123-4567")
data.SetVariable("contactEmail", "[email protected]")
data.SetVariable("contactAddress", "上海市浦东新区科技园区")
// 创建产品列表(包含图片)
products := []interface{}{
map[string]interface{}{
"name": "智能音箱 Pro",
"model": "AS-2024-Pro",
"price": "¥599",
"inStock": true,
"hasPromotion": true,
"promotionText": "限时9折优惠",
"features": []interface{}{"AI语音助手", "360度环绕音效", "智能家居控制"},
"productImage": "speaker_image", // 图片变量名
},
map[string]interface{}{
"name": "智能手表 Elite",
"model": "SW-2024-Elite",
"price": "¥1,299",
"inStock": true,
"hasPromotion": false,
"features": []interface{}{"健康监测", "GPS定位", "7天续航"},
"productImage": "watch_image",
},
map[string]interface{}{
"name": "无线耳机 Max",
"model": "WE-2024-Max",
"price": "¥299",
"inStock": false,
"hasPromotion": false,
"features": []interface{}{"主动降噪", "无线充电", "防水设计"},
"productImage": "earphone_image",
},
}
data.SetList("products", products)
// 为每个产品配置图片
// 图片1:智能音箱(紫色背景)
speakerImageConfig := &document.ImageConfig{
Position: document.ImagePositionInline,
Alignment: document.AlignCenter,
Size: &document.ImageSize{
Width: 80,
KeepAspectRatio: true,
},
AltText: "智能音箱产品图片",
Title: "智能音箱 Pro",
}
speakerImageData := createProductImage(200, 150, "智能音箱", color.RGBA{200, 150, 255, 255})
data.SetImageFromData("speaker_image", speakerImageData, speakerImageConfig)
// 图片2:智能手表(蓝色背景)
watchImageConfig := &document.ImageConfig{
Position: document.ImagePositionInline,
Alignment: document.AlignCenter,
Size: &document.ImageSize{
Width: 70,
KeepAspectRatio: true,
},
AltText: "智能手表产品图片",
Title: "智能手表 Elite",
}
watchImageData := createProductImage(150, 150, "智能手表", color.RGBA{150, 200, 255, 255})
data.SetImageFromData("watch_image", watchImageData, watchImageConfig)
// 图片3:无线耳机(绿色背景)
earphoneImageConfig := &document.ImageConfig{
Position: document.ImagePositionInline,
Alignment: document.AlignCenter,
Size: &document.ImageSize{
Width: 75,
KeepAspectRatio: true,
},
AltText: "无线耳机产品图片",
Title: "无线耳机 Max",
}
earphoneImageData := createProductImage(180, 120, "无线耳机", color.RGBA{150, 255, 200, 255})
data.SetImageFromData("earphone_image", earphoneImageData, earphoneImageConfig)
// 渲染并保存
doc, err := engine.RenderToDocument("product_catalog", data)
if err != nil {
log.Fatalf("渲染产品目录失败: %v", err)
}
err = doc.Save("examples/output/product_catalog_with_images.docx")
if err != nil {
log.Fatalf("保存产品目录失败: %v", err)
}
fmt.Println("✓ 产品目录图片模板演示完成,文档已保存为 product_catalog_with_images.docx")
}
// createProductImage 创建产品展示图片(辅助函数)
func createProductImage(width, height int, text string, bgColor color.RGBA) []byte {
img := image.NewRGBA(image.Rect(0, 0, width, height))
// 填充背景色
for y := 0; y < height; y++ {
for x := 0; x < width; x++ {
img.Set(x, y, bgColor)
}
}
// 添加边框
borderColor := color.RGBA{0, 0, 0, 255}
for x := 0; x < width; x++ {
img.Set(x, 0, borderColor)
img.Set(x, height-1, borderColor)
}
for y := 0; y < height; y++ {
img.Set(0, y, borderColor)
img.Set(width-1, y, borderColor)
}
// 转换为PNG
buf := new(bytes.Buffer)
png.Encode(buf, img)
return buf.Bytes()
}
7. 产品手册模板
func generateProductManual() {
engine := document.NewTemplateEngine()
manualTemplate := `{{extends "base_manual"}}
{{#block "content"}}
产品手册
产品名称:{{productName}}
版本号:{{version}}
发布日期:{{releaseDate}}
产品概述:
{{productDescription}}
主要特性:
{{#each features}}
{{@index}}. {{title}}
{{description}}
{{#if isBeta}}
🚧 测试版功能
{{/if}}
{{#if isNew}}
✨ 新功能
{{/if}}
{{/each}}
系统要求:
操作系统:{{#each systemRequirements.os}}{{this}}{{#unless @last}}、{{/unless}}{{/each}}
内存:最低 {{systemRequirements.minMemory}},推荐 {{systemRequirements.recommendedMemory}}
磁盘空间:{{systemRequirements.diskSpace}}
安装步骤:
{{#each installationSteps}}
步骤 {{@index}}:{{title}}
{{#if hasDetails}}
{{details}}
{{/if}}
{{#if hasWarning}}
⚠️ {{warning}}
{{/if}}
{{/each}}
使用指南:
{{#each usageGuides}}
{{title}}
{{content}}
{{#if hasExample}}
示例:
{{example}}
{{/if}}
{{/each}}
{{#if hasTroubleshooting}}
常见问题:
{{#each troubleshooting}}
问题:{{question}}
解答:{{answer}}
{{/each}}
{{/if}}
技术支持:
支持邮箱:{{supportEmail}}
支持电话:{{supportPhone}}
{{#if hasOnlineSupport}}
在线支持:{{supportUrl}}
{{/if}}
{{/block}}
`
// 首先创建基础模板
baseTemplate := `{{companyName}}
{{#block "header"}}
{{title}}
版本:{{version}}
{{/block}}
{{#block "content"}}
默认内容
{{/block}}
{{#block "footer"}}
版权所有 © {{year}} {{companyName}}
技术支持:{{supportContact}}
{{/block}}`
engine.LoadTemplate("base_manual", baseTemplate)
engine.LoadTemplate("product_manual", manualTemplate)
data := document.NewTemplateData()
// 基础信息
data.SetVariable("companyName", "WordZero科技")
data.SetVariable("title", "WordZero企业版用户手册")
data.SetVariable("year", "2024")
data.SetVariable("supportContact", "[email protected]")
// 产品信息
data.SetVariable("productName", "WordZero企业版")
data.SetVariable("version", "v2.1.0")
data.SetVariable("releaseDate", "2024年12月1日")
data.SetVariable("productDescription", "WordZero是一款专业的Go语言Word文档处理库,提供完整的文档创建、编辑和格式化功能。")
// 产品特性
features := []interface{}{
map[string]interface{}{
"title": "强大的模板引擎",
"description": "支持变量替换、条件语句、循环处理和模板继承,轻松创建动态文档。",
"isBeta": false,
"isNew": true,
},
map[string]interface{}{
"title": "丰富的表格功能",
"description": "完整的表格创建、编辑、样式设置和数据处理功能。",
"isBeta": false,
"isNew": false,
},
map[string]interface{}{
"title": "智能样式管理",
"description": "预定义样式库和自定义样式支持,保持文档格式统一。",
"isBeta": true,
"isNew": true,
},
}
data.SetList("features", features)
// 系统要求
data.SetVariable("systemRequirements", map[string]interface{}{
"os": []interface{}{"Windows 10+", "macOS 10.15+", "Linux"},
"minMemory": "4GB",
"recommendedMemory": "8GB",
"diskSpace": "100MB",
})
// 安装步骤
steps := []interface{}{
map[string]interface{}{
"title": "下载安装包",
"hasDetails": true,
"details": "从官网下载最新版本的安装包。",
"hasWarning": false,
},
map[string]interface{}{
"title": "安装Go环境",
"hasDetails": true,
"details": "确保系统已安装Go 1.16或更高版本。",
"hasWarning": true,
"warning": "不支持Go 1.15及以下版本",
},
}
data.SetList("installationSteps", steps)
// 使用指南
guides := []interface{}{
map[string]interface{}{
"title": "快速开始",
"content": "创建第一个Word文档只需几行代码。",
"hasExample": true,
"example": "doc := document.New()\ndoc.AddParagraph(\"Hello WordZero!\")\ndoc.Save(\"hello.docx\")",
},
}
data.SetList("usageGuides", guides)
// 常见问题
faq := []interface{}{
map[string]interface{}{
"question": "如何设置中文字体?",
"answer": "使用SetFontFamily方法,推荐使用系统内置字体如'Microsoft YaHei'。",
},
}
data.SetList("troubleshooting", faq)
// 支持信息
data.SetVariable("supportEmail", "[email protected]")
data.SetVariable("supportPhone", "400-888-0000")
data.SetVariable("supportUrl", "https://support.wordzero.com")
data.SetCondition("hasTroubleshooting", true)
data.SetCondition("hasOnlineSupport", true)
// 渲染并保存
doc, _ := engine.RenderTemplateToDocument("product_manual", data)
doc.Save("product_manual.docx")
}
最佳实践
1. 模板设计原则
优先使用 TemplateRenderer ✨
// ✅ 推荐:使用 TemplateRenderer
renderer := document.NewTemplateRenderer()
renderer.SetLogging(true)
template, _ := renderer.LoadTemplateFromFile("invoice", "templates/invoice.docx")
doc, _ := renderer.RenderTemplate("invoice", data)
// ❌ 不推荐:直接使用 TemplateEngine(除非有特殊需求)
engine := document.NewTemplateEngine()
template, _ := engine.LoadTemplate("invoice", content)
doc, _ := engine.RenderTemplateToDocument("invoice", data)
保持模板简洁
// ✅ 好的做法
templateContent := `
订单确认
订单号:{{orderNumber}}
{{#if isExpress}}
配送方式:快递配送
{{/if}}
`
// ❌ 避免复杂嵌套
templateContent := `
{{#each orders}}
{{#if isValid}}
{{#each items}}
{{#if isAvailable}}
// 过度嵌套,难以维护
{{/if}}
{{/each}}
{{/if}}
{{/each}}
`
利用模板分析功能
// ✅ 使用模板分析了解结构
renderer := document.NewTemplateRenderer()
analysis, _ := renderer.AnalyzeTemplate("complex_template")
// 检查模板复杂度
if len(analysis.Variables) > 20 {
log.Println("警告:模板变量过多,考虑拆分")
}
if len(analysis.Tables) > 5 {
log.Println("警告:表格数量较多,注意性能")
}
使用有意义的变量名
// ✅ 清晰的变量名
data.SetVariable("customerName", "张三")
data.SetVariable("orderDate", "2024-12-01")
data.SetVariable("deliveryAddress", "上海市浦东新区...")
// ❌ 模糊的变量名
data.SetVariable("n", "张三")
data.SetVariable("d", "2024-12-01")
data.SetVariable("addr", "上海市浦东新区...")
2. 数据组织
合理使用结构体
type OrderInfo struct {
OrderNumber string
CustomerName string
OrderDate string
TotalAmount float64
IsExpressDelivery bool
}
// 使用结构体自动填充模板数据
order := OrderInfo{
OrderNumber: "ORD20241201001",
CustomerName: "张三",
OrderDate: "2024-12-01",
TotalAmount: 299.99,
IsExpressDelivery: true,
}
data := document.NewTemplateData()
data.FromStruct(order)
处理字段名冲突
// 当多个结构体有相同字段名时,手动设置变量
type Company struct {
Name string
}
type Employee struct {
Name string
}
company := Company{Name: "WordZero科技"}
employee := Employee{Name: "张三"}
data := document.NewTemplateData()
data.SetVariable("companyName", company.Name)
data.SetVariable("employeeName", employee.Name)
3. 模板缓存管理
// 在应用启动时预加载常用模板
func initTemplates(engine *document.TemplateEngine) {
templates := map[string]string{
"invoice": loadTemplateFile("invoice.tmpl"),
"report": loadTemplateFile("report.tmpl"),
"contract": loadTemplateFile("contract.tmpl"),
}
for name, content := range templates {
engine.LoadTemplate(name, content)
}
}
// 定期清理缓存
func cleanupTemplateCache(engine *document.TemplateEngine) {
// 根据业务需要定期清理
engine.ClearCache()
}
4. 错误处理策略
func renderTemplate(engine *document.TemplateEngine, templateName string, data *document.TemplateData) (*document.Document, error) {
// 验证模板是否存在
template, err := engine.GetTemplate(templateName)
if err != nil {
return nil, fmt.Errorf("template not found: %s", templateName)
}
// 验证模板语法
if err := engine.ValidateTemplate(template); err != nil {
return nil, fmt.Errorf("template validation failed: %v", err)
}
// 渲染模板
doc, err := engine.RenderTemplateToDocument(templateName, data)
if err != nil {
return nil, fmt.Errorf("template rendering failed: %v", err)
}
return doc, nil
}
错误处理
模板相关错误类型
WordZero定义了以下模板相关错误:
// 模板未找到
ErrTemplateNotFound = NewDocumentError("template_not_found", fmt.Errorf("template not found"), "")
// 模板语法错误
ErrTemplateSyntaxError = NewDocumentError("template_syntax_error", fmt.Errorf("template syntax error"), "")
// 模板渲染错误
ErrTemplateRenderError = NewDocumentError("template_render_error", fmt.Errorf("template render error"), "")
// 无效模板数据
ErrInvalidTemplateData = NewDocumentError("invalid_template_data", fmt.Errorf("invalid template data"), "")
模板验证
ValidateTemplate(template *Template)
验证模板语法的正确性。
template, err := engine.LoadTemplate("test", templateContent)
if err != nil {
log.Fatal(err)
}
// 验证模板语法
err = engine.ValidateTemplate(template)
if err != nil {
log.Printf("Template validation failed: %v", err)
return
}
验证内容包括:
- 括号配对:检查
{{
和}}
是否正确配对 - if语句配对:检查
{{#if}}
和{{/if}}
是否正确配对 - each语句配对:检查
{{#each}}
和{{/each}}
是否正确配对
常见错误及解决方案
1. 模板语法错误
// 错误:括号不匹配
badTemplate := `Hello {{name}!`
// 正确:括号匹配
goodTemplate := `Hello {{name}}!`
2. 条件语句不匹配
// 错误:缺少结束标签
badTemplate := `{{#if condition}}Hello`
// 正确:完整的条件语句
goodTemplate := `{{#if condition}}Hello{{/if}}`
3. 循环语句不匹配
// 错误:缺少结束标签
badTemplate := `{{#each items}}{{name}}`
// 正确:完整的循环语句
goodTemplate := `{{#each items}}{{name}}{{/each}}`
4. 数据类型不匹配
// 错误:设置错误的数据类型
data.SetList("name", "张三") // name应该是变量,不是列表
// 正确:使用正确的数据类型
data.SetVariable("name", "张三")
性能优化
1. 模板缓存
模板引擎内置了缓存机制,自动缓存已加载的模板。
// 第一次加载模板(较慢)
template1, _ := engine.LoadTemplate("test", content)
// 后续获取模板(很快,从缓存获取)
template2, _ := engine.GetTemplate("test")
2. 批量数据设置
// ✅ 推荐:批量设置变量
variables := map[string]interface{}{
"name": "张三",
"age": 30,
"email": "[email protected]",
"phone": "138-0000-0000",
}
data.SetVariables(variables)
// ❌ 避免:逐个设置(性能较差)
data.SetVariable("name", "张三")
data.SetVariable("age", 30)
data.SetVariable("email", "[email protected]")
data.SetVariable("phone", "138-0000-0000")
3. 数据预处理
// 预处理复杂数据,避免在模板中进行复杂计算
func prepareOrderData(order *Order) *document.TemplateData {
data := document.NewTemplateData()
// 预计算总金额
total := calculateTotal(order.Items)
// 预处理日期格式
formattedDate := order.Date.Format("2006年01月02日")
data.SetVariable("total", total)
data.SetVariable("orderDate", formattedDate)
return data
}
4. 模板复用
// 创建可复用的基础模板
baseTemplate := `
{{companyName}}
{{title}}
创建时间:{{createDate}}
---
`
// 基于基础模板创建不同类型的文档
userManualTemplate := `{{extends "base"}}
用户手册内容...
`
apiDocTemplate := `{{extends "base"}}
API文档内容...
`
5. 内存管理
// 在不需要时清理模板缓存
func cleanupResources(engine *document.TemplateEngine) {
// 清空所有缓存
engine.ClearCache()
// 或者移除特定模板
engine.RemoveTemplate("large_template")
}
// 及时清理模板数据
func processTemplate() {
data := document.NewTemplateData()
// ... 使用数据
// 处理完成后清理
data.Clear()
}
模板示例索引
本文档包含了丰富的模板示例,覆盖了各种实际应用场景。以下是快速索引:
📊 商务文档模板
-
商业发票模板 - 查看示例
- 发票基本信息、商品明细、费用计算
- 条件显示(折扣、税费、付款状态)
- 复杂的列表循环和嵌套条件
-
会议记录模板 - 查看示例
- 会议基本信息、出席人员管理
- 议程讨论、决议和行动项跟踪
- 嵌套循环和复杂数据结构处理
-
商务合同模板 - 查看示例
- 甲乙双方信息、合同条款
- 付款计划和特殊条款
- 从现有DOCX模板文件加载
👨💼 人力资源模板
- 员工绩效报告 - 查看示例
- 员工基本信息、绩效评分
- 成就列表、改进建议
- 结构体数据自动绑定
🎓 教育培训模板
- 学生成绩单模板 - 查看示例
- 学生基本信息、课程成绩
- 学科能力分析、出勤统计
- 综合评价和家长反馈
🖼️ 图片模板示例 ✨ 新增特性
- 产品目录图片模板 - 查看示例
- 图片占位符语法展示
- 多图片配置和样式设置
- 循环中的图片处理
📖 技术文档模板
- 产品手册模板 - 查看示例
- 产品特性、系统要求
- 安装指南、使用说明
- 模板继承和块重写机制展示
⚙️ 模板功能特性演示
每个示例都展示了不同的模板功能:
模板功能 | 发票 | 绩效 | 会议 | 成绩 | 图片 | 合同 | 手册 |
---|---|---|---|---|---|---|---|
变量替换 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
条件语句 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
循环语句 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
嵌套循环 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
循环上下文变量 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
图片占位符 | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ |
结构体绑定 | ❌ | ✅ | ❌ | ✅ | ❌ | ❌ | ❌ |
模板继承 | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ |
现有DOCX支持 | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ |
🎯 选择合适的示例
根据您的需求选择合适的示例:
- 初学者: 从发票模板开始,学习基础语法
- 复杂数据处理: 查看会议记录和成绩单模板
- 结构体集成: 学习绩效报告的数据绑定方式
- 图片处理: 查看产品目录图片模板,学习图片占位符使用 ✨ 推荐
- 模板继承: 研究产品手册的高级模板功能
- 现有模板集成: 参考合同模板的DOCX加载方式
💡 实践建议
- 从简单开始: 先掌握变量替换和基础条件语句
- 逐步进阶: 再学习循环语句和嵌套结构
- 实际应用: 选择与您业务相近的模板进行改造
- 测试验证: 每个功能都要充分测试,确保输出符合预期
总结
WordZero的模板功能为动态文档生成提供了强大而灵活的解决方案。通过合理使用变量替换、条件渲染、循环处理和模板继承等特性,您可以轻松创建复杂的动态文档。
核心要点
- 模板渲染器:使用
NewTemplateRenderer()
创建渲染器实例(推荐) - 模板引擎:使用
NewTemplateEngine()
创建引擎实例(底层API) - 模板加载:支持从字符串、现有文档和DOCX文件加载模板
- 数据绑定:支持手动设置和结构体自动绑定
- 语法支持:变量、条件、循环、图片占位符、继承等完整语法
- 图片处理:支持
{{#image 变量名}}
语法插入图片,配置丰富 ✨ 新增 - 模板分析:自动分析模板结构和依赖关系
- 日志记录:完善的日志系统,便于调试和监控
- 错误处理:完善的验证和错误处理机制
- 性能优化:内置缓存和优化建议
实现状态
所有文档中提及的功能都已完全实现并经过测试:
- ✅ 模板引擎核心功能
- ✅ 模板渲染器高级封装 ✨ 新增
- ✅ 变量替换和条件渲染
- ✅ 循环处理和上下文变量
- ✅ 图片占位符功能 ✨ 新增特性
- ✅ 模板继承机制
- ✅ 结构体数据绑定
- ✅ 模板分析功能 ✨ 新增
- ✅ 从DOCX文件加载模板 ✨ 新增
- ✅ 完善的日志记录系统 ✨ 新增
- ✅ 模板数据自动验证 ✨ 新增
- ✅ 模板验证和错误处理
- ✅ 缓存管理和性能优化
- ✅ 完整的测试用例
通过本教程,您应该能够熟练使用WordZero的模板功能来满足各种动态文档生成需求。