Skip to content

ThinkDH 模板开发文档

目录

  1. 模板开发概述
  2. 设计理念
  3. 应用场景
  4. 开发规范
  5. HTML标签规范
  6. 支持的自定义HTML标签
  7. 标签属性说明
  8. 标签嵌套规则
  9. 模板使用指南
  10. 模板创建步骤
  11. 模板引用、继承和复用
  12. 变量使用、条件判断、循环等模板语法说明
  13. 配置文件说明
  14. 所有配置项的详细说明
  15. 配置文件的加载顺序和优先级规则
  16. 示例模板
  17. 基础模板示例
  18. 复杂嵌套模板示例
  19. 动态数据绑定模板示例
  20. 示例配置文件
  21. 不同场景的配置示例
  22. 完整配置文件示例

1. 模板开发概述

1.1 设计理念

ThinkDH 模板系统采用了分离设计理念,将模板的结构、样式、配置和业务逻辑完全分离,使模板开发者可以专注于模板的设计和功能实现,而不需要关心系统层面的配置处理。

核心设计理念包括:

  • 配置驱动:通过 config.json 文件定义模板的配置项,系统自动生成可视化的配置表单
  • 模块化:支持组件化开发,模板可以包含多个独立的组件
  • 灵活性:模板开发者可以自由定义模板的结构和样式
  • 可扩展性:支持自定义配置项,满足不同模板的个性化需求
  • 易于使用:提供简洁明了的模板语法,降低开发门槛

1.2 应用场景

ThinkDH 模板系统适用于以下场景:

  • 网站首页定制:通过模板系统可以快速定制网站首页的布局和内容
  • 分类页面定制:为不同的分类页面创建不同的模板
  • 专题页面创建:快速创建各种专题页面,如活动页面、推广页面等
  • 多语言支持:通过模板配置可以实现多语言支持
  • 个性化展示:根据不同的用户群体展示不同的内容

1.3 开发规范

模板开发应遵循以下规范:

  • 目录结构:模板文件应按照规定的目录结构组织
  • 文件命名:文件名应使用小写字母和下划线,避免使用特殊字符
  • 代码规范:HTML代码应遵循标准的HTML5规范,保持代码整洁
  • 性能优化:模板应考虑性能优化,避免过多的嵌套和复杂的逻辑
  • 安全性:模板代码应注意安全性,避免XSS等安全问题
  • 兼容性:模板应考虑不同浏览器的兼容性

2. HTML标签规范

2.1 支持的自定义HTML标签

ThinkDH 模板系统支持以下自定义HTML标签:

标签名描述用途
{volist}循环标签用于遍历数组数据
{if}条件判断标签用于条件判断
{else}条件判断标签用于条件判断的else分支
{elseif}条件判断标签用于条件判断的elseif分支
{/if}条件判断标签用于结束条件判断
{php}PHP代码标签用于执行PHP代码
{$variable}变量输出标签用于输出变量值

2.2 标签属性说明

{volist} 标签属性

| 属性名 | 类型 | 必填 | 默认值 | 描述 | |-------|------|--------|------| | name | string | 是 | 无 | 要遍历的变量名 | | id | string | 否 | 无 | 循环体中的变量名 | | offset | number | 否 | 0 | 起始偏移量 | | length | number | 否 | 无 | 循环长度 | | key | string | 否 | 无 | 循环的键名 | | mod | string | 否 | 无 | 取模运算 |

{if} 标签属性

| 属性名 | 类型 | 必填 | 默认值 | 描述 | |-------|------|--------|------| | condition | string | 是 | 无 | 条件表达式 |

2.3 标签嵌套规则

标签嵌套应遵循以下规则:

  1. {volist} 标签可以嵌套其他标签,包括 {if}{volist}
  2. {if} 标签可以嵌套其他标签,包括 {if}{volist}
  3. 标签必须正确闭合,如 {if}...{/if}{volist}...{/volist}
  4. 嵌套层次不宜过深,建议不超过3层,以保证模板的可读性和性能

3. 模板使用指南

3.1 模板创建步骤和最佳实践

模板创建步骤

  1. 创建模板目录:在 template 目录下创建一个新的目录,作为模板的根目录
  2. 创建配置文件:在模板根目录下创建 config.json 文件,定义模板的配置项
  3. 创建HTML文件:在模板根目录下创建 html 目录,并在其中创建HTML文件
  4. 创建组件文件:在模板根目录下创建 components 目录,并在其中创建组件文件
  5. 创建静态资源:在模板根目录下创建 cssjsimg 等目录,存放静态资源

最佳实践

  • 模块化设计:将模板拆分为多个组件,提高代码的可维护性和复用性
  • 配置驱动:充分利用 config.json 文件,使模板具有更大的灵活性
  • 性能优化:减少模板中的复杂逻辑,避免过多的嵌套
  • 代码规范:保持代码整洁,添加必要的注释
  • 测试:在开发过程中及时测试模板的效果

3.2 模板引用、继承和复用的具体方法

模板引用

在模板中引用其他模板文件:

html
{include file="template/dev/components/header.html"}

模板继承

ThinkDH 模板系统支持模板继承,通过以下方式实现:

  1. 定义基础模板:创建一个基础模板文件,包含公共部分
  2. 继承基础模板:在子模板中继承基础模板,并覆盖需要修改的部分

模板复用

模板复用可以通过以下方式实现:

  • 组件化:将重复使用的部分封装为组件,在多个模板中引用
  • 配置化:通过配置文件控制模板的行为,实现模板的复用
  • 变量化:使用变量代替硬编码的值,提高模板的复用性

3.3 变量使用、条件判断、循环等模板语法说明

变量使用

在模板中使用变量:

html
{$variable} <!-- 输出变量值 -->
{$thinkdh.path_tpl} <!-- 输出系统变量 -->
{$templateConfig.speaker.notice} <!-- 输出配置变量 -->

条件判断

在模板中使用条件判断:

html
{if condition="$templateConfig.home.components['dating-zone']"}
    <!-- 条件为真时显示的内容 -->
{else}
    <!-- 条件为假时显示的内容 -->
{/if}

{if condition="$app.status == 1"}
    <!-- 条件为真时显示的内容 -->
{elseif condition="$app.status == 2"}
    <!-- 条件为真时显示的内容 -->
{else}
    <!-- 条件为假时显示的内容 -->
{/if}

循环

在模板中使用循环:

html
{volist name="templateConfig.banner" id="banner"}
    <div class="swiper-slide">
        <a href="{$banner.url}" target="_blank">
            <img src="{$banner.img}" alt="">
        </a>
    </div>
{/volist}

PHP代码执行

在模板中执行PHP代码:

html
{php}echo rand(100, 200);{/php}

4. 配置文件说明

4.1 配置文件的标准格式和存储路径

配置文件格式

配置文件采用JSON格式,包含以下两部分:

  1. _config:定义配置项的元数据,包括字段类型、标签、描述等
  2. 根级别配置:定义配置项的默认值

存储路径

配置文件存储在模板根目录下,路径为:

template/{template_id}/config.json

其中 {template_id} 是模板的唯一标识,如 devdefault 等。

4.2 所有配置项的详细说明

配置文件结构

配置文件的基本结构如下:

json
{
  "_config": {
    "group1": {
      "label": "配置组标签",
      "description": "配置组描述",
      "fields": {
        "field1": {
          "label": "字段标签",
          "type": "字段类型",
          "description": "字段描述",
          "required": true,
          "default": "默认值"
        }
      }
    },
    "group1": {
      "field1": "默认值"
    }
  }
}

支持的字段类型

类型描述用途
text文本输入框用于输入单行文本
textarea文本域用于输入多行文本
number数字输入框用于输入数字
boolean布尔开关用于开启/关闭某个功能
array数组用于存储多个值
object对象用于存储复杂结构的数据
image图片上传用于上传图片

配置项说明

配置项类型默认值用途
speakerobject{}公告设置
speaker.noticestring""公告内容
speaker.downstring""下载链接
bannerarray[]轮播图配置
banner[].idstring""轮播图ID
banner[].urlstring""轮播图链接
banner[].imgstring""轮播图图片
optionsobject{}选项设置
options.pricearray[]价格选项
options.servicearray[]服务选项
options.projectarray[]项目选项
subtitlearray[]副标题设置
lfobject{}随机数据设置
lf.likeobject{}点赞数范围
lf.like.minnumber0最小点赞数
lf.like.maxnumber0最大点赞数
lf.addobject{}添加数范围
lf.add.minnumber0最小添加数
lf.add.maxnumber0最大添加数
homeobject{}首页设置
home.componentsobject{}组件设置
home.components.dating-zonebooleanfalse是否显示同城约会组件
categoriesarray[]分类设置
categories[].idnumber0分类ID
categories[].namestring""分类名称
categories[].iconstring""分类图标
categories[].componentsobject{}分类组件设置

4.3 配置文件的加载顺序和优先级规则

配置文件的加载顺序和优先级如下:

  1. 默认配置:系统首先加载模板目录下的 config.json 文件
  2. 用户配置:然后加载用户在后台修改后的配置
  3. 运行时配置:最后加载运行时生成的配置
  4. 优先级:运行时配置 > 用户配置 > 默认配置

5. 示例模板

5.1 基础模板示例

首页基础模板

html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>{$title}</title>
    <link rel="stylesheet" href="{$thinkdh.path_tpl}css/home.css">
    <script src="{$thinkdh.path_tpl}js/rem.min.js"></script>
</head>
<body>
    <div id="app">
        <!-- 公告区域 -->
        <div class="marquee-wrap">
            <div class="marquee-box">
                <div class="icon-speaker"></div>
                <div class="container-main">
                    <p>{$templateConfig.speaker.notice}</p>
                </div>
                <a href="{$templateConfig.speaker.down}" target="_blank" class="btn-more">下载APP</a>
            </div>
        </div>

        <!-- 轮播图 -->
        <div id="swiper-banner" class="swiper">
            <div class="swiper-wrapper">
                {volist name="templateConfig.banner" id="banner"}
                <div class="swiper-slide">
                    <a href="{$banner.url}" target="_blank">
                        <img src="{$banner.img}" alt="">
                    </a>
                </div>
                {/volist}
            </div>
            <div class="swiper-pagination"></div>
        </div>

        <!-- 导航 -->
        <div class="nav-c">
            <div class="item active">
                <em>全部</em>
            </div>
            {volist name="templateConfig.categories" id="vo"}
            <div class="item">
                <em>{$vo.name}</em>
            </div>
            {/volist}
        </div>

        <!-- 内容区域 -->
        <div class="content">
            <!-- 内容区域 -->
        </div>
    </div>

    <script src="{$thinkdh.path_tpl}js/swiper-bundle.min.js"></script>
    <script>
        // 初始化轮播图
        var swiper = new Swiper('#swiper-banner', {
            pagination: {
                el: '.swiper-pagination',
            },
            autoplay: {
                delay: 3000,
                disableOnInteraction: false,
            },
        });
    </script>
</body>
</html>

5.2 复杂嵌套模板示例

分类页面模板

html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>{$title}</title>
    <link rel="stylesheet" href="{$thinkdh.path_tpl}css/home.css">
    <script src="{$thinkdh.path_tpl}js/rem.min.js"></script>
</head>
<body>
    <div id="app">
        <!-- 导航 -->
        <div class="nav-c">
            <div class="item active">
                <em>全部</em>
            </div>
            {volist name="templateConfig.categories" id="vo"}
            <div class="item">
                <em>{$vo.name}</em>
            </div>
            {/volist}
        </div>

        <!-- 分类内容 -->
        <div class="swiper-c">
            <div class="swiper-wrapper">
                <!-- 全部部分类 -->
                <div class="swiper-slide">
                    <div>
                        <div>官方推荐 <span class="f-title"> Recommend </span></div>
                    </div>
                </div>
                <div class="grid-cols-5">
                        {volist name="recommendApps[1]" id="app"}
                        <a class="grid-item" href="{$app.url}" target="_blank">
                            <img src="{$app.img}" alt="{$app.name}">
                            <div class="text">{$app.name}</div>
                            <div class="jgg-load">进入</div>
                        </a>
                        {/volist}
                    </div>
                </div>
            </div>

            <!-- 各个分类 -->
            {volist name="templateConfig.categories" id="category"}
                <div class="swiper-slide">
                    <div>
                        <div>{$category.name} <span class="f-title"> Category </span></div>
                    </div>
                    <div class="grid-cols-5">
                        {volist name="categoryApps[$category.id]" id="app"}
                        <a class="grid-item" href="{$app.url}" target="_blank">
                            <img src="{$app.img}" alt="{$app.name}">
                            <div class="text">{$app.name}</div>
                            <div class="jgg-load">进入</div>
                        </a>
                        {/volist}
                    </div>
                </div>

                <!-- 同城约会组件 -->
                {if condition="$category.components['dating-zone']"}
                    <div class="lf title-item">
                        <div>
                            <div>同城约会 <span class="f-title"> DatingZone </span></div>
                        </div>
                    </div>
                    <div class="zone-wrap">
                        {volist name="categoryApps[4]" id="app"}
                        <a class="zone-item" href="{$app.url}" target="_blank">
                            <img src="{$app.img}" alt="">
                            <div class="zone1-text-wrap">
                                <p class="zone1-item-name-wrap">
                                    <span class="zone1-item-name">{$app.name}</span>
                                    <span class="zone1-item-color1">
                                        {php}echo $templateConfig['subtitle'][array_rand($templateConfig['subtitle'])];{/php}
                                    </span>
                                </p>
                            </div>
                        </a>
                        {/volist}
                    </div>
                    {/if}
                </div>
                {/volist}
            </div>
        </div>
    </div>

    <script src="{$thinkdh.path_tpl}js/swiper-bundle.min.js"></script>
    <script>
        // 初始化分类轮播
        var swiper = new Swiper('.swiper-c', {
            slidesPerView: 1,
            spaceBetween: 0,
            freeMode: true,
        });
    </script>
</body>
</html>

5.3 动态数据绑定模板示例

动态内容模板

html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>{$title}</title>
    <link rel="stylesheet" href="{$thinkdh.path_tpl}css/home.css">
    <script src="{$thinkdh.path_tpl}js/rem.min.js"></script>
</head>
<body>
    <div id="app">
        <!-- 随机数据展示 -->
        <div class="lf title-item">
            <div>
                <div>关注我们 <span class="f-title"> Stay in care </span></div>
            </div>
        </div>

        <div class="zp-wrap">
            {volist name="categoryApps[5]" id="app"}
                <div class="zp-wrap-item">
                    <a href="{$app.url}" target="_blank">
                        <div class="item-s4">
                            <div class="header">
                                <div class="cover">
                                    <img src="{$app.img}" alt="">
                                </div>
                            </div>
                            <div class="flex-1">
                                <div class="name">{$app.name}</div>
                                <div class="flex flex-middle">
                                    <div class="icon-address"></div>
                                    距离 {php}echo rand($templateConfig['lf']['add']['min'], $templateConfig['lf']['add']['max']);{/php}km
                                </div>
                            </div>
                            <div class="btn-detail">查看详细信息</div>
                        </div>
                        <div class="fc-gray">
                            {$app.description|default=''}
                        </div>
                    </div>
                </a>
            </div>
            {/volist}
        </div>

        <!-- 价格和服务选项 -->
        <div class="gt title-item">
            <div>
                <div>价格和服务 <span class="f-title"> Price & Service </span></div>
            </div>
        </div>
        <div class="options-wrap">
            <div class="options-item">
                <h3>价格选项</h3>
                <ul>
                    {volist name="templateConfig.options.price" id="price"}
                    <li>{$price}</li>
                    {/volist}
                </ul>
            </div>
            <div class="options-item">
                <h3>服务选项</h3>
                <ul>
                    {volist name="templateConfig.options.service" id="service"}
                    <li>{$service}</li>
                    {/volist}
                </ul>
            </div>
        </div>
    </div>
</body>
</html>

6. 示例配置文件

6.1 完整配置文件示例

基础配置文件示例

json
{
  "_config": {
    "speaker": {
      "label": "公告设置",
      "description": "公告和下载链接设置",
      "fields": {
        "notice": {
          "label": "公告",
          "type": "textarea",
          "description": "网站公告内容",
          "required": true
        },
        "down": {
          "label": "下载链接",
          "type": "text",
          "description": "应用下载链接",
          "required": true
        }
      }
    },
    "banner": {
      "label": "轮播设置",
      "description": "首页轮播图配置",
      "type": "array",
      "itemFields": {
        "id": {
          "label": "ID",
          "type": "text",
          "description": "轮播图ID"
        },
        "url": {
          "label": "链接",
          "type": "text",
          "description": "轮播图点击链接"
        },
        "img": {
          "label": "图片",
          "type": "image",
          "description": "轮播图图片"
        }
      }
    },
    "options": {
      "label": "选项设置",
      "description": "价格和服务选项配置",
      "fields": {
        "price": {
          "label": "价格选项",
          "type": "array",
          "itemType": "text",
          "description": "价格选项列表"
        },
        "service": {
          "label": "服务选项",
          "type": "array",
          "itemType": "text",
          "description": "服务选项列表"
        },
        "project": {
          "label": "项目选项",
          "type": "array",
          "itemType": "text",
          "description": "项目选项列表"
        }
      }
    },
    "subtitle": {
      "label": "副标题设置",
      "description": "副标题配置",
      "type": "array",
      "itemType": "text",
      "description": "副标题列表"
    },
    "lf": {
      "label": "随机数据设置",
      "description": "随机数据生成配置",
      "fields": {
        "like": {
          "label": "点赞数范围",
          "type": "object",
          "fields": {
            "min": {
              "label": "最小值",
              "type": "number",
              "description": "点赞数最小值"
            },
            "max": {
              "label": "最大值",
              "type": "number",
              "description": "点赞数最大值"
            }
          }
        },
        "add": {
          "label": "添加数范围",
          "type": "object",
          "fields": {
            "min": {
              "label": "最小值",
              "type": "number",
              "description": "添加数最小值"
            },
            "max": {
              "label": "最大值",
              "type": "number",
              "description": "添加数最大值"
            }
          }
        }
      }
    },
    "home": {
      "label": "首页设置",
      "description": "首页组件显示配置",
      "fields": {
        "components": {
          "label": "组件设置",
          "type": "object",
          "fields": {
            "dating-zone": {
              "label": "同城组件",
              "type": "boolean",
              "description": "是否显示同城约会组件"
            },
            "s-wrap": {
              "label": "卡片组件",
              "type": "boolean",
              "description": "是否显示卡片组件"
            }
          }
        }
      }
    },
    "categories": {
      "label": "分类设置",
      "description": "网站分类配置",
      "type": "array",
      "itemFields": {
        "id": {
          "label": "分类ID",
          "type": "number",
          "description": "分类唯一标识"
        },
        "name": {
          "label": "分类名称",
          "type": "text",
          "description": "分类显示名称"
        },
        "icon": {
          "label": "分类图标",
          "type": "text",
          "description": "分类图标路径"
        },
        "components": {
          "label": "组件设置",
          "type": "object",
          "fields": {
            "dating-zone": {
              "label": "同城组件",
              "type": "boolean",
              "description": "是否显示同城约会组件"
            }
          }
        }
      }
    }
  },
  "speaker": {
    "notice": "欢迎使用ThinkDH模板系统!",
    "down": "https://thinkdh.com"
  },
  "banner": [
    {
      "id": "1",
      "url": "https://thinkdh.com",
      "img": "https://appimg-drcn.dbankcdn.com/application/screenshut1/619076b692a54c0483b3266bf8edfdb4.jpg"
    },
    {
      "id": "2",
      "url": "https://thinkdh.com",
      "img": "https://appimg-drcn.dbankcdn.com/application/screenshut1/619076b692a54c0483b3266bf8edfdb4.jpg"
    }
  ],
  "options": {
    "price": [
      "1200/C 2000/Y",
      "1800/C 2000/Y"
    ],
    "service": [
      "介绍相亲 上门提亲",
      "在线预约 线下面谈"
    ],
    "project": [
      "全场督办 相亲 婚礼",
      "酒席 婚礼 潦队"
    ]
  },
  "subtitle": [
    "(168/45kg/D)",
    "(168/51kg/C)"
  ],
  "lf": {
    "like": {
      "min": 666,
      "max": 3000
    },
    "add": {
      "min": 10,
      "max": 20
    }
  },
  "home": {
    "banner": 1,
    "notice": 1,
    "components": {
      "dating-zone": 1,
      "s-wrap": 1
    }
  },
  "categories": [
    {
      "id": 1,
      "name": "视频",
      "icon": "",
      "components": {
        "dating-zone": 1,
        "s-wrap": 1
      }
    },
    {
      "id": 2,
      "name": "直播",
      "icon": "",
      "components": {
        "dating-zone": 1,
        "s-wrap": 1
      }
    },
    {
      "id": 3,
      "name": "交友",
      "icon": "",
      "components": {
        "dating-zone": 1,
        "s-wrap": 1
      }
    },
    {
      "id": 4,
      "name": "同城",
      "icon": "",
      "components": {
        "dating-zone": 1,
        "s-wrap": 1
      }
    },
    {
      "id": 5,
      "name": "游戏",
      "icon": "",
      "components": {
        "dating-zone": 1,
        "s-wrap": 1
      }
    },
    {
      "id": 6,
      "name": "阅读",
      "icon": "",
      "components": {
        "dating-zone": 1,
        "s-wrap": 1
      }
    }
  ]
}

6.2 不同场景的配置示例

多语言配置示例

json
{
  "_config": {
    "language": {
      "label": "语言设置",
      "description": "多语言支持配置",
      "fields": {
        "default": {
          "label": "默认语言",
          "type": "text",
          "description": "默认语言代码,如 zh-CN, en-US 等"
        },
        "supported": {
          "label": "支持的语言",
          "type": "array",
          "itemType": "text",
          "description": "支持的语言代码列表"
        }
      }
    }
  },
  "translations": {
    "zh-CN": {
      "title": "ThinkDH 官方网站",
      "description": "ThinkDH 是一个企业级应用导航系统"
    },
    "en-US": {
      "title": "ThinkDH Official Website",
      "description": "ThinkDH is an enterprise application navigation system"
    }
  },
  "language": {
    "default": "zh-CN",
    "supported": ["zh-CN", "en-US"]
  }
}

专题页面配置示例

json
{
  "_config": {
    "topic": {
      "label": "专题设置",
      "description": "专题页面配置",
      "fields": {
        "title": {
          "label": "专题标题",
          "type": "text",
          "description": "专题页面标题"
        },
        "description": {
          "label": "专题描述",
          "type": "textarea",
          "description": "专题页面描述"
        },
        "banner": {
          "label": "专题 banner",
          "type": "image",
          "description": "专题页面顶部 banner"
        },
        "items": {
          "label": "专题内容",
          "type": "array",
          "itemFields": {
            "title": {
              "label": "项目标题",
              "type": "text",
              "description": "项目标题"
            },
            "image": {
              "label": "项目图片",
              "type": "image",
              "description": "项目图片"
            },
            "description": {
              "label": "项目描述",
              "type": "textarea",
              "description": "项目描述"
            },
            "url": {
              "label": "项目链接",
              "type": "text",
              "description": "项目链接"
            }
          }
        }
      }
    }
  },
  "topic": {
    "title": "2026 新年专题",
    "description": "庆祝 2026 新年,推出多项优惠活动",
    "banner": "https://example.com/2026-new-year.jpg",
    "items": [
      {
        "title": "优惠活动 1",
        "image": "https://example.com/item1.jpg",
        "description": "活动详情 1",
        "url": "https://example.com/event1"
      },
      {
        "title": "优惠活动 2",
        "image": "https://example.com/item2.jpg",
        "description": "活动详情 2",
        "url": "https://example.com/event2"
      }
    ]
  }
}

7. 总结

ThinkDH 模板系统是一个功能强大、灵活易用的模板开发系统,通过配置文件驱动的方式,使模板开发者可以快速创建各种类型的模板。本文档详细介绍了模板系统的设计理念、使用方法和最佳实践,希望能够帮助开发人员快速理解并正确使用模板系统。

如果您在使用过程中遇到任何问题,请参考本文档或联系技术支持。


文档版本:1.0
更新日期:2026-02-10
作者:ThinkDH 开发团队