# 模板引擎系统

<cite>
**本文引用的文件**
- [public/themes/default/public/base.html](file://public/themes/default/public/base.html)
- [public/themes/admin_default/public/base.html](file://public/themes/admin_default/public/base.html)
- [public/themes/default/public/head.html](file://public/themes/default/public/head.html)
- [public/themes/default/public/scripts.html](file://public/themes/default/public/scripts.html)
- [public/themes/admin_default/public/header.html](file://public/themes/admin_default/public/header.html)
- [public/themes/default/portal/article.html](file://public/themes/default/portal/article.html)
- [public/themes/default/portal/list.html](file://public/themes/default/portal/list.html)
- [public/themes/default/public/function.html](file://public/themes/default/public/function.html)
- [public/themes/default/public/widgets/slider/widget.html](file://public/themes/default/public/widgets/slider/widget.html)
- [public/themes/admin_default/admin/theme/file_widgets.html](file://public/themes/admin_default/admin/theme/file_widgets.html)
- [public/themes/admin_default/admin/theme/widget_setting.html](file://public/themes/admin_default/admin/theme/widget_setting.html)
- [public/themes/admin_default/admin/theme/scripts.html](file://public/themes/admin_default/admin/theme/scripts.html)
- [public/themes/admin_default/admin/main/index.html](file://public/themes/admin_default/admin/main/index.html)
</cite>

## 目录
1. [简介](#简介)
2. [项目结构](#项目结构)
3. [核心组件](#核心组件)
4. [架构总览](#架构总览)
5. [详细组件分析](#详细组件分析)
6. [依赖分析](#依赖分析)
7. [性能考虑](#性能考虑)
8. [故障排查指南](#故障排查指南)
9. [结论](#结论)
10. [附录](#附录)

## 简介
本文件系统性梳理 ThinkCMF 模板引擎体系，围绕以下主题展开：模板继承与基础模板（base.html）的作用、区块（Block）系统的设计与覆盖、变量传递（全局、局部、模板变量）、模板包含与嵌套、条件渲染与循环遍历、模板调试与错误处理、以及性能优化与缓存策略。文档以仓库中的实际模板文件为依据，通过图示与分层讲解帮助读者快速掌握模板引擎的工作原理与最佳实践。

## 项目结构
ThinkCMF 的模板采用“主题 + 子模板”的组织方式，公共头部、脚本、区块等通过包含（include）与区块（block）机制在不同主题间复用。默认主题与管理端主题分别提供各自的 base.html 作为继承根，子模板通过 extend 与 block 实现差异化覆盖。

```mermaid
graph TB
subgraph "默认主题"
D_Base["public/themes/default/public/base.html"]
D_Head["public/themes/default/public/head.html"]
D_Scripts["public/themes/default/public/scripts.html"]
D_Article["public/themes/default/portal/article.html"]
D_List["public/themes/default/portal/list.html"]
D_Function["public/themes/default/public/function.html"]
D_Widget["public/themes/default/public/widgets/slider/widget.html"]
end
subgraph "管理端主题"
A_Base["public/themes/admin_default/public/base.html"]
A_Header["public/themes/admin_default/public/header.html"]
A_FileWidgets["public/themes/admin_default/admin/theme/file_widgets.html"]
A_WidgetSetting["public/themes/admin_default/admin/theme/widget_setting.html"]
A_Scripts["public/themes/admin_default/admin/theme/scripts.html"]
A_Main["public/themes/admin_default/admin/main/index.html"]
end
D_Article --> D_Base
D_List --> D_Base
D_Base --> D_Head
D_Base --> D_Scripts
D_Widget --> D_Base
A_FileWidgets --> A_WidgetSetting
A_WidgetSetting --> A_Scripts
A_Main --> A_WidgetSetting
A_Base --> A_Header
```

图表来源
- [public/themes/default/public/base.html:1-30](file://public/themes/default/public/base.html#L1-L30)
- [public/themes/default/public/head.html:1-59](file://public/themes/default/public/head.html#L1-L59)
- [public/themes/default/public/scripts.html:1-74](file://public/themes/default/public/scripts.html#L1-L74)
- [public/themes/default/portal/article.html:1-7](file://public/themes/default/portal/article.html#L1-L7)
- [public/themes/default/portal/list.html:1-7](file://public/themes/default/portal/list.html#L1-L7)
- [public/themes/default/public/function.html:1-20](file://public/themes/default/public/function.html#L1-L20)
- [public/themes/default/public/widgets/slider/widget.html:1-30](file://public/themes/default/public/widgets/slider/widget.html#L1-L30)
- [public/themes/admin_default/public/base.html:1-11](file://public/themes/admin_default/public/base.html#L1-L11)
- [public/themes/admin_default/public/header.html:1-84](file://public/themes/admin_default/public/header.html#L1-L84)
- [public/themes/admin_default/admin/theme/file_widgets.html:31-57](file://public/themes/admin_default/admin/theme/file_widgets.html#L31-L57)
- [public/themes/admin_default/admin/theme/widget_setting.html:37-88](file://public/themes/admin_default/admin/theme/widget_setting.html#L37-L88)
- [public/themes/admin_default/admin/theme/scripts.html:22-55](file://public/themes/admin_default/admin/theme/scripts.html#L22-L55)
- [public/themes/admin_default/admin/main/index.html:220-399](file://public/themes/admin_default/admin/main/index.html#L220-L399)

章节来源
- [public/themes/default/public/base.html:1-30](file://public/themes/default/public/base.html#L1-L30)
- [public/themes/admin_default/public/base.html:1-11](file://public/themes/admin_default/public/base.html#L1-L11)

## 核心组件
- 基础模板（base.html）
  - 默认主题与管理端主题均提供 base.html，作为模板继承的根节点。默认主题 base.html 定义了 SEO 区块、公共头尾包含、widgets 区块布局；管理端 base.html 提供 head/main/scripts 区块，便于后台页面差异化定制。
- 包含（include）与标签库（taglib）
  - 通过 include 引入公共 head/scripts 或 function 文件；通过 taglib 注册自定义标签库，扩展模板能力。
- 区块（block）
  - 子模板通过 extend 继承 base，使用 block 覆盖父级同名区块，实现差异化输出（如 SEO 标题、关键词、描述等）。
- 变量与函数
  - 支持模板内 PHP 逻辑（如变量赋值、条件判断、循环），以及在 function.html 中定义的自定义函数，用于模板中调用。
- 小部件（widget）与区块挂载
  - 使用 widgetsBlock/ widgetsHead/ widgetsScript 等指令将小部件挂载到指定区块，实现页面布局的可视化拼装。

章节来源
- [public/themes/default/public/base.html:1-30](file://public/themes/default/public/base.html#L1-L30)
- [public/themes/admin_default/public/base.html:1-11](file://public/themes/admin_default/public/base.html#L1-L11)
- [public/themes/default/public/head.html:1-59](file://public/themes/default/public/head.html#L1-L59)
- [public/themes/default/public/scripts.html:1-74](file://public/themes/default/public/scripts.html#L1-L74)
- [public/themes/default/public/function.html:1-20](file://public/themes/default/public/function.html#L1-L20)
- [public/themes/default/portal/article.html:1-7](file://public/themes/default/portal/article.html#L1-L7)
- [public/themes/default/portal/list.html:1-7](file://public/themes/default/portal/list.html#L1-L7)

## 架构总览
模板渲染遵循“基础模板 + 子模板覆盖 + 公共包含”的三层结构。默认主题与管理端主题分别提供各自的基础模板，子模板通过 extend 选择继承路径，再以 block 覆盖具体区块内容。公共 head/scripts 通过 include 复用，确保一致的资源加载与脚本执行顺序。

```mermaid
sequenceDiagram
participant View as "子模板"
participant Base as "基础模板(base.html)"
participant Head as "公共头部(head.html)"
participant Scripts as "公共脚本(scripts.html)"
View->>Base : "extend 继承"
View->>Base : "block 覆盖(如 seo)"
Base->>Head : "include 引入"
Base->>Scripts : "include 引入"
Base-->>View : "渲染完成"
```

图表来源
- [public/themes/default/public/base.html:1-30](file://public/themes/default/public/base.html#L1-L30)
- [public/themes/default/public/head.html:1-59](file://public/themes/default/public/head.html#L1-L59)
- [public/themes/default/public/scripts.html:1-74](file://public/themes/default/public/scripts.html#L1-L74)
- [public/themes/default/portal/article.html:1-7](file://public/themes/default/portal/article.html#L1-L7)

## 详细组件分析

### 模板继承与基础模板（base.html）
- 默认主题 base.html
  - 定义了 SEO 区块，用于注入标题、关键词、描述；
  - 通过 include 引入公共 head/scripts；
  - 通过 widgetsHead/ widgetsScript/ widgetsBlock 挂载区块与小部件，形成响应式布局。
- 管理端 base.html
  - 提供 head/main/scripts 区块，便于后台页面统一结构与脚本注入。

```mermaid
flowchart TD
Start(["进入子模板"]) --> Extend["extend 继承 base.html"]
Extend --> BlockOverride["block 覆盖(如 seo)"]
BlockOverride --> IncludeHead["include 引入 head.html"]
BlockOverride --> IncludeScripts["include 引入 scripts.html"]
IncludeHead --> WidgetsMount["widgetsHead/ widgetsBlock/ widgetsScript 挂载"]
IncludeScripts --> WidgetsMount
WidgetsMount --> RenderEnd(["输出最终 HTML"])
```

图表来源
- [public/themes/default/public/base.html:1-30](file://public/themes/default/public/base.html#L1-L30)
- [public/themes/default/public/head.html:1-59](file://public/themes/default/public/head.html#L1-L59)
- [public/themes/default/public/scripts.html:1-74](file://public/themes/default/public/scripts.html#L1-L74)

章节来源
- [public/themes/default/public/base.html:1-30](file://public/themes/default/public/base.html#L1-L30)
- [public/themes/admin_default/public/base.html:1-11](file://public/themes/admin_default/public/base.html#L1-L11)

### 区块（Block）系统设计与使用
- 区块定义与覆盖
  - 子模板通过 extend 选择继承路径，再以 block 覆盖父级同名区块。例如文章页与列表页分别覆盖 SEO 区块，注入动态标题与描述。
- 标准区块
  - 默认主题：seo、widgetsHead、widgetsScript、多列 body 区块；
  - 管理端：head、main、scripts。

```mermaid
sequenceDiagram
participant Child as "子模板(article/list)"
participant Parent as "父级base"
participant SEO as "SEO 区块"
Child->>Parent : "extend 继承"
Child->>SEO : "block 覆盖(注入标题/关键词/描述)"
Parent-->>Child : "渲染后输出"
```

图表来源
- [public/themes/default/portal/article.html:1-7](file://public/themes/default/portal/article.html#L1-L7)
- [public/themes/default/portal/list.html:1-7](file://public/themes/default/portal/list.html#L1-L7)
- [public/themes/default/public/base.html:1-30](file://public/themes/default/public/base.html#L1-L30)

章节来源
- [public/themes/default/portal/article.html:1-7](file://public/themes/default/portal/article.html#L1-L7)
- [public/themes/default/portal/list.html:1-7](file://public/themes/default/portal/list.html#L1-L7)

### 变量传递机制（全局、局部、模板变量）
- 局部变量与模板变量
  - 子模板中可直接使用模板变量（如站点信息、文章信息等），并通过 PHP 逻辑进行赋值或条件判断。
- 全局变量
  - 在公共 head 中定义全局 JS 变量（如 GV），供前端脚本使用。
- 自定义函数
  - 在 function.html 中定义模板可用的 PHP 函数，供模板调用。

```mermaid
flowchart TD
Init(["模板初始化"]) --> LoadGlobal["加载全局变量(GV)"]
Init --> LoadFunc["加载自定义函数(function.html)"]
LoadGlobal --> Render["渲染模板变量"]
LoadFunc --> Render
Render --> Output(["输出 HTML"])
```

图表来源
- [public/themes/default/public/head.html:48-59](file://public/themes/default/public/head.html#L48-L59)
- [public/themes/default/public/function.html:1-20](file://public/themes/default/public/function.html#L1-L20)

章节来源
- [public/themes/default/public/head.html:48-59](file://public/themes/default/public/head.html#L48-L59)
- [public/themes/default/public/function.html:1-20](file://public/themes/default/public/function.html#L1-L20)

### 模板包含与嵌套
- include 机制
  - base.html 通过 include 引入 head/scripts，实现资源与脚本的集中管理。
- 嵌套与组合
  - 小部件（widget）通过特定标签与区块指令挂载到页面，形成“区块 + 小部件”的嵌套组合。

```mermaid
graph LR
Base["base.html"] --> HeadInc["include head.html"]
Base --> ScriptInc["include scripts.html"]
Widget["slider/widget.html"] --> Base
```

图表来源
- [public/themes/default/public/base.html:9-27](file://public/themes/default/public/base.html#L9-L27)
- [public/themes/default/public/widgets/slider/widget.html:1-30](file://public/themes/default/public/widgets/slider/widget.html#L1-L30)

章节来源
- [public/themes/default/public/base.html:9-27](file://public/themes/default/public/base.html#L9-L27)
- [public/themes/default/public/widgets/slider/widget.html:1-30](file://public/themes/default/public/widgets/slider/widget.html#L1-L30)

### 条件渲染与循环遍历
- 条件渲染
  - 在模板中使用条件判断（如后台调试开关）控制区块输出。
- 循环遍历
  - 后台页面通过循环渲染仪表盘小部件，支持系统与插件小部件的差异化展示。

```mermaid
flowchart TD
LoopStart(["开始循环"]) --> CheckCond{"条件满足?"}
CheckCond --> |是| RenderItem["渲染单项"]
CheckCond --> |否| Skip["跳过"]
RenderItem --> Next["下一项"]
Skip --> Next
Next --> |有更多| CheckCond
Next --> |无更多| LoopEnd(["结束循环"])
```

图表来源
- [public/themes/admin_default/admin/main/index.html:220-399](file://public/themes/admin_default/admin/main/index.html#L220-L399)

章节来源
- [public/themes/admin_default/admin/main/index.html:220-399](file://public/themes/admin_default/admin/main/index.html#L220-L399)

### 小部件（Widget）系统与区块挂载
- 小部件定义
  - 小部件模板通过特定标签与变量（如 vars、css）定义可配置项。
- 区块挂载
  - 通过 widgetsHead/ widgetsScript/ widgetsBlock 将小部件挂载到指定区块，实现页面布局的可视化拼装。
- 后台配置
  - 后台提供小部件选择、排序与保存功能，通过脚本更新区块内的小部件顺序与配置。

```mermaid
sequenceDiagram
participant Admin as "后台页面"
participant FileWidgets as "file_widgets.html"
participant WidgetSetting as "widget_setting.html"
participant Scripts as "scripts.html"
Admin->>FileWidgets : "浏览可用小部件"
Admin->>WidgetSetting : "打开小部件设置"
WidgetSetting->>Scripts : "引入区块脚本"
Scripts-->>Admin : "拖拽排序/保存配置"
```

图表来源
- [public/themes/admin_default/admin/theme/file_widgets.html:31-57](file://public/themes/admin_default/admin/theme/file_widgets.html#L31-L57)
- [public/themes/admin_default/admin/theme/widget_setting.html:37-88](file://public/themes/admin_default/admin/theme/widget_setting.html#L37-L88)
- [public/themes/admin_default/admin/theme/scripts.html:22-55](file://public/themes/admin_default/admin/theme/scripts.html#L22-L55)

章节来源
- [public/themes/admin_default/admin/theme/file_widgets.html:31-57](file://public/themes/admin_default/admin/theme/file_widgets.html#L31-L57)
- [public/themes/admin_default/admin/theme/widget_setting.html:37-88](file://public/themes/admin_default/admin/theme/widget_setting.html#L37-L88)
- [public/themes/admin_default/admin/theme/scripts.html:22-55](file://public/themes/admin_default/admin/theme/scripts.html#L22-L55)

## 依赖分析
- 组件耦合
  - 子模板对基础模板存在强依赖（extend），对公共包含（include）存在弱依赖（head/scripts）。小部件与区块之间通过指令解耦，便于独立维护。
- 导入关系
  - 默认主题与管理端主题分别维护各自的 base.html 与公共包含文件，避免跨主题污染。
- 可能的循环依赖
  - 模板包含采用单向依赖（base -> head/scripts），未见循环包含迹象。

```mermaid
graph TB
Article["article.html"] --> BaseDefault["default/base.html"]
List["list.html"] --> BaseDefault
BaseDefault --> Head["head.html"]
BaseDefault --> Scripts["scripts.html"]
Slider["slider/widget.html"] --> BaseDefault
```

图表来源
- [public/themes/default/portal/article.html:1-7](file://public/themes/default/portal/article.html#L1-L7)
- [public/themes/default/portal/list.html:1-7](file://public/themes/default/portal/list.html#L1-L7)
- [public/themes/default/public/base.html:1-30](file://public/themes/default/public/base.html#L1-L30)
- [public/themes/default/public/head.html:1-59](file://public/themes/default/public/head.html#L1-L59)
- [public/themes/default/public/scripts.html:1-74](file://public/themes/default/public/scripts.html#L1-L74)
- [public/themes/default/public/widgets/slider/widget.html:1-30](file://public/themes/default/public/widgets/slider/widget.html#L1-L30)

章节来源
- [public/themes/default/portal/article.html:1-7](file://public/themes/default/portal/article.html#L1-L7)
- [public/themes/default/portal/list.html:1-7](file://public/themes/default/portal/list.html#L1-L7)
- [public/themes/default/public/base.html:1-30](file://public/themes/default/public/base.html#L1-L30)

## 性能考虑
- 资源合并与按需加载
  - 将公共样式与脚本集中在 head/scripts 中，减少重复请求；仅在需要时引入额外脚本。
- 区块化与延迟渲染
  - 将非首屏内容放入区块并在滚动或交互时按需渲染，降低初始渲染压力。
- 小部件懒加载
  - 对图片类小部件采用懒加载策略，减少首屏带宽占用。
- 缓存策略
  - 后台页面可通过区块脚本保存用户偏好与布局，减少重复配置开销。
- 模板编译与静态化
  - 对不频繁变动的页面（如静态列表页）可考虑静态化输出，结合 CDN 加速。

## 故障排查指南
- 区块未生效
  - 检查子模板是否正确 extend 基础模板，且 block 名称与父级一致。
- 资源未加载
  - 确认 include 路径正确，head/scripts 是否被正确引入。
- 小部件不显示
  - 检查 widgetsHead/ widgetsScript/ widgetsBlock 指令是否正确挂载，后台区块脚本是否正常运行。
- 变量未解析
  - 确认变量已在模板上下文中定义，或在 function.html 中注册了相应函数。
- 调试模式
  - 后台模板中可通过调试开关显示调试面板，辅助定位问题。

章节来源
- [public/themes/admin_default/public/header.html:77-84](file://public/themes/admin_default/public/header.html#L77-L84)
- [public/themes/admin_default/admin/theme/scripts.html:22-55](file://public/themes/admin_default/admin/theme/scripts.html#L22-L55)

## 结论
ThinkCMF 模板引擎通过“基础模板 + 区块覆盖 + 公共包含 + 小部件挂载”的设计，实现了高复用、低耦合的页面构建方式。默认主题与管理端主题分别提供清晰的继承根与区块规范，配合条件渲染与循环遍历，满足复杂业务场景下的页面定制需求。建议在实践中遵循区块命名规范、合理拆分小部件、利用缓存与懒加载提升性能，并通过调试面板快速定位问题。

## 附录
- 关键文件索引
  - 默认主题基础模板：[public/themes/default/public/base.html:1-30](file://public/themes/default/public/base.html#L1-L30)
  - 管理端基础模板：[public/themes/admin_default/public/base.html:1-11](file://public/themes/admin_default/public/base.html#L1-L11)
  - 公共头部与脚本：[public/themes/default/public/head.html:1-59](file://public/themes/default/public/head.html#L1-L59)、[public/themes/default/public/scripts.html:1-74](file://public/themes/default/public/scripts.html#L1-L74)
  - 子模板示例：[public/themes/default/portal/article.html:1-7](file://public/themes/default/portal/article.html#L1-L7)、[public/themes/default/portal/list.html:1-7](file://public/themes/default/portal/list.html#L1-L7)
  - 小部件示例：[public/themes/default/public/widgets/slider/widget.html:1-30](file://public/themes/default/public/widgets/slider/widget.html#L1-L30)
  - 后台区块与脚本：[public/themes/admin_default/admin/theme/file_widgets.html:31-57](file://public/themes/admin_default/admin/theme/file_widgets.html#L31-L57)、[public/themes/admin_default/admin/theme/widget_setting.html:37-88](file://public/themes/admin_default/admin/theme/widget_setting.html#L37-L88)、[public/themes/admin_default/admin/theme/scripts.html:22-55](file://public/themes/admin_default/admin/theme/scripts.html#L22-L55)
  - 后台循环渲染示例：[public/themes/admin_default/admin/main/index.html:220-399](file://public/themes/admin_default/admin/main/index.html#L220-L399)