12 模板功能 - ZeroHawkeye/wordZero GitHub Wiki

模板功能实现教程

WordZero 提供了强大的模板引擎功能,支持动态内容生成、变量替换、条件渲染、循环处理等高级特性。本教程将详细介绍如何使用模板功能来创建动态文档。

目录

  1. 模板引擎概述
  2. 核心概念
  3. 基础功能
  4. 高级功能
  5. 实际应用示例
  6. 模板示例索引
  7. 最佳实践
  8. 错误处理
  9. 性能优化

模板引擎概述

什么是模板引擎

模板引擎是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()
}

模板示例索引

本文档包含了丰富的模板示例,覆盖了各种实际应用场景。以下是快速索引:

📊 商务文档模板

  1. 商业发票模板 - 查看示例

    • 发票基本信息、商品明细、费用计算
    • 条件显示(折扣、税费、付款状态)
    • 复杂的列表循环和嵌套条件
  2. 会议记录模板 - 查看示例

    • 会议基本信息、出席人员管理
    • 议程讨论、决议和行动项跟踪
    • 嵌套循环和复杂数据结构处理
  3. 商务合同模板 - 查看示例

    • 甲乙双方信息、合同条款
    • 付款计划和特殊条款
    • 从现有DOCX模板文件加载

👨‍💼 人力资源模板

  1. 员工绩效报告 - 查看示例
    • 员工基本信息、绩效评分
    • 成就列表、改进建议
    • 结构体数据自动绑定

🎓 教育培训模板

  1. 学生成绩单模板 - 查看示例
    • 学生基本信息、课程成绩
    • 学科能力分析、出勤统计
    • 综合评价和家长反馈

🖼️ 图片模板示例 ✨ 新增特性

  1. 产品目录图片模板 - 查看示例
    • 图片占位符语法展示
    • 多图片配置和样式设置
    • 循环中的图片处理

📖 技术文档模板

  1. 产品手册模板 - 查看示例
    • 产品特性、系统要求
    • 安装指南、使用说明
    • 模板继承和块重写机制展示

⚙️ 模板功能特性演示

每个示例都展示了不同的模板功能:

模板功能 发票 绩效 会议 成绩 图片 合同 手册
变量替换
条件语句
循环语句
嵌套循环
循环上下文变量
图片占位符
结构体绑定
模板继承
现有DOCX支持

🎯 选择合适的示例

根据您的需求选择合适的示例:

  • 初学者: 从发票模板开始,学习基础语法
  • 复杂数据处理: 查看会议记录和成绩单模板
  • 结构体集成: 学习绩效报告的数据绑定方式
  • 图片处理: 查看产品目录图片模板,学习图片占位符使用 ✨ 推荐
  • 模板继承: 研究产品手册的高级模板功能
  • 现有模板集成: 参考合同模板的DOCX加载方式

💡 实践建议

  1. 从简单开始: 先掌握变量替换和基础条件语句
  2. 逐步进阶: 再学习循环语句和嵌套结构
  3. 实际应用: 选择与您业务相近的模板进行改造
  4. 测试验证: 每个功能都要充分测试,确保输出符合预期

总结

WordZero的模板功能为动态文档生成提供了强大而灵活的解决方案。通过合理使用变量替换、条件渲染、循环处理和模板继承等特性,您可以轻松创建复杂的动态文档。

核心要点

  1. 模板渲染器:使用 NewTemplateRenderer() 创建渲染器实例(推荐)
  2. 模板引擎:使用 NewTemplateEngine() 创建引擎实例(底层API)
  3. 模板加载:支持从字符串、现有文档和DOCX文件加载模板
  4. 数据绑定:支持手动设置和结构体自动绑定
  5. 语法支持:变量、条件、循环、图片占位符、继承等完整语法
  6. 图片处理:支持 {{#image 变量名}} 语法插入图片,配置丰富 ✨ 新增
  7. 模板分析:自动分析模板结构和依赖关系
  8. 日志记录:完善的日志系统,便于调试和监控
  9. 错误处理:完善的验证和错误处理机制
  10. 性能优化:内置缓存和优化建议

实现状态

所有文档中提及的功能都已完全实现并经过测试:

  • ✅ 模板引擎核心功能
  • ✅ 模板渲染器高级封装 ✨ 新增
  • ✅ 变量替换和条件渲染
  • ✅ 循环处理和上下文变量
  • ✅ 图片占位符功能 ✨ 新增特性
  • ✅ 模板继承机制
  • ✅ 结构体数据绑定
  • ✅ 模板分析功能 ✨ 新增
  • ✅ 从DOCX文件加载模板 ✨ 新增
  • ✅ 完善的日志记录系统 ✨ 新增
  • ✅ 模板数据自动验证 ✨ 新增
  • ✅ 模板验证和错误处理
  • ✅ 缓存管理和性能优化
  • ✅ 完整的测试用例

通过本教程,您应该能够熟练使用WordZero的模板功能来满足各种动态文档生成需求。