ZsAdmin「智数」BBS社区插件 前端模板标签文档

张森森
张森森 主理璃海华章
管理员
插件开发 135 浏览 0 回复
详情摘要ZsAdmin - GPT

【总结】本文详细介绍了ZsAdmin「智数」BBS社区插件的前端模板标签使用规范,包括基础输出、布局片段、条件循环、过滤器、助手函数、JSON输出等核心功能,重点强调了模板语法常见坑与解决方案,如避免未转义花括号、慎用raw过滤器等,

本站前台(社区插件等)使用 ThinkPHP 模板引擎(think-template)。模板目录主要在:

  • plugins/community/view/front/
  • 主题覆盖:themes//community/(若启用)

编译缓存:runtime/temp/。改模板后若异常,可清缓存或后台「清理缓存」。


1. 基础输出

写法说明
{$name}输出变量(自动转义 HTML)
{$user.nickname}数组 / 对象属性
{$a.b.c}多级属性
`{$name\raw}`
`{$title\default='未命名'}`
`{$n\default=0}`
{$compose_title|default='发布新帖'}
{$topic.content|raw}

函数调用输出

{:community_url('topic', ['id' => $item.id])}
{:hook_slot('plaza_feed_top')}

{: ... } 内写 PHP 表达式,返回值直接输出。


2. 布局与片段

继承布局

{extend name="layout" /}

{block name="title"}页面标题{/block}
{block name="css"}...{/block}
{block name="content"}...{/block}
{block name="js"}...{/block}

引入片段

{include file="_plaza_left" /}
{include file="_captcha_field" /}

相对当前 view/front/;以下划线 _ 开头的一般为局部片段。


3. 条件与循环

if / else / elseif

{if $edit_mode}
  编辑
{elseif !empty($lock_compose_type)}
  锁定类型
{else /}
  新建
{/if}

注意:else / elseif 后常带空格与 /,写成 {else /}、{elseif ...}。

{if ($edit_mode && $topic.category_id==$c.id) || (!$edit_mode && $pre_category_id==$c.id)}on{/if}

空判断

{empty name="replies"}暂无回复{/empty}
{notempty name="user"}已登录{/notempty}

volist(推荐列表)

{volist name="categories" id="c"}
  {$c.name}
{/volist}
属性说明
name数据集变量名
id循环项变量
key可选,下标变量名
offset / length可选切片

foreach

{foreach $list as $key => $item}
  {$key}: {$item.title}
{/foreach}


4. 修饰符(过滤器)

常用:

修饰符示例说明
default`{$x\default=''}`
raw`{$json\raw}`
date`{$time\date='Y-m-d'}`

可串联:{$html|default=''|raw}(慎用;raw 一般放最后)。


5. 本站助手函数

在模板里用 {:函数名(...)} 调用。定义位置见括号。

路由 / 链接

函数定义用法
community_urlplugins/community/helpers.php{:community_url('topic', ['id' => $id])}
message_url同上 / message 插件{:messageurl('messagesend')}
payment_urlpayment 插件{:payment_url('recharge')}

community_url 常用路由名(可被后台「路由」配置改写):

名称默认路径含义
plaza广场首页
boards版块列表
category版块 ['id'=>…]
topic帖子详情 ['id'=>…]
topic_create发帖 ['type'=>'article']
topic_edit编辑 ['id'=>…]
topic_save保存(POST)
articles / questions / topics …各内容模型聚合页
member / login / register会员与登录
page单页 ['slug'=>…]
tag标签 ['id'=>…]
user主页 ['type'=>'user','id'=>…]

插槽 / 资源

函数定义说明
hook_slotapp/common.php插件插槽 HTML
plugin_assets同上已装插件的前台 CSS/JS
{:hook_slot('compose_body', ['content' => '', 'required' => true])}
{:hook_slot('compose_extra', ['edit_mode' => false, 'topic_id' => 0])}
{:plugin_assets()}

常见插槽名:composebody、composeextra、composeassets、plazafeedtop、topicauthorbadges、afteruser_level 等(由各插件注册)。

UI 组件

函数说明
ucavatarhtml([...])头像 + 等级环/角标
levelprogresshtml($progress)等级进度条
communitycaticon_html($icon)版块 Remix(Remix 或图片)
communitymediaurl($url)媒体 URL 规范化
adsboot / adsafter_section广告位(未装 ads 插件时返回空)

头像示例:

{:uc_avatar_html([
  'src'   => $author.avatar,
  'color' => $author.user_level_color,
  'badge' => $author.user_level_badge,
  'size'  => 'sm',
  'href'  => $author.profile_url,
  'alt'   => $author.nickname
])}

size:xs / sm / md / lg / xl。

货币文案

函数说明
paymentcoinname()积分名
paymentgoldname()金币名
paymentcurrencylabel($c)按币种返回文案

模板里也常用控制器下发的 {$coinname}、{$goldname}。


6. 在模板里输出 JSON 给 JS

推荐(控制器已保证有值):


try {
  var map = JSON.parse('{$model_fields_map_json|raw}') || {};
} catch (e) {
  var map = {};
}

对象字面量直接嵌入(已是合法 JS):

guangyaDirect: {$guangya_direct_json|raw},

控制器侧请用 jsonencode(..., JSONUNESCAPEDUNICODE | JSONHEXTAG | JSONHEXAPOS | JSONHEXQUOT | JSONHEX_AMP),避免 XSS。


7. 重要坑(必读)

7.1 标签内禁止未转义的 }

ThinkPHP 用 { } 定界。标签内容里再出现 } 会被当成标签结束,轻则编译失败,重则整页 HTTP 500。

错误(曾导致发帖页登录后 500):

{$model_fields_map_json|default="{}"|raw}

解析到 default="{}" 的 } 即截断,报错类似:Unclosed '(' does not match '}'。

正确:

{$model_fields_map_json|raw}

或默认值不要含花括号:

{$x|default='[]'|raw}
{$x|default=''}

同理避免:


{if $a == "{}"}...{/if}
{$color|default='#64748b'}  

颜色类默认值本站已在用 default='#64748b';若遇解析问题,改为控制器赋默认值再 {$color}。

7.2 {: } 里尽量简单

复杂三元、嵌套括号可放到控制器或助手函数,模板只调用:


{:hook_slot('compose_extra', ['topic_id' => !empty($a) ? (int)(is_object($t) ? ($t->id ?? 0) : 0) : 0])}


{:hook_slot('compose_extra', ['edit_mode' => !empty($edit_mode), 'topic_id' => (int)$compose_topic_id])}

7.3 |raw 只用于可信内容

用户正文须先经 HtmlSanitizer 等净化,再 |raw。未知字符串一律默认转义输出。

7.4 未登录与已登录路径不同

部分页面未登录会 redirect,不渲染模板;登录后才编译模板。因此「只有登录后 500」往往是模板语法问题,而不是权限逻辑。

7.5 改模板后清缓存

php think clear

或删除 runtime/temp/ 下相关编译文件。生产环境若存在 runtime/config.php 且含其它机器绝对路径,也需清理后重新生成。


8. 原生 PHP 片段(少用)

{php}
$ptCount = isset($post_types) ? count($post_types) : 1;
{/php}

仅用于布局里临时兼容变量;新代码优先在控制器 View::assign。


9. 自定义模型发帖页约定

发帖页 create.html 关键变量(控制器 Index::create / edit):

变量含义
$edit_mode是否编辑
$compose_type内容模型:discussion / article / …
$lockcomposetype锁定模型(URL ?type= 或编辑时)
$categories可选版块列表
$modelfieldsmap_json自定义字段定义 JSON
$topiccustomvalues_json编辑时字段值 JSON
$typetitlesjson / $typeleadsjson切换版块时标题文案

模型专属模板:后台可配 createtemplate*,解析为 create/.html(如 create/blank.html)。


10. 速查对照


{$var}  {$a.b}  {$var|default=''}  {$html|raw}  {:func()}


{extend name="layout" /}
{block name="content"}...{/block}
{include file="_partial" /}


{if}{elseif}{else /}{/if}
{volist name="list" id="item"}{/volist}
{empty name="list"}{/empty}


{:community_url('topic', ['id' => $id])}
{:hook_slot('slot_name', [...])}
{:uc_avatar_html([...])}
{:community_cat_icon_html($c.icon)}


11. 相关文件

路径内容
app/common.phphookslot、ucavatarhtml、pluginassets
plugins/community/helpers.phpcommunity_url 等社区助手
plugins/community/view/front/layout.html前台主布局
plugins/community/view/front/create.html发帖页(含 JSON 输出范例)
plugins/community/service/FrontRoute.php路由名与默认 path
vendor/topthink/think-template/引擎源码与官方能力

官方手册:ThinkPHP 模板引擎

评论0
回复 · 0
还没有回复
微信客服 微信客服 QQ官方交流群 QQ官方交流群