Discuz! 的模板系统是基于文件和目录的,通过修改特定的模板文件,你可以自由地改变列表页的样式和布局。

核心文件位置
分类信息列表页的模板文件主要位于以下目录:
/source/class/table/ - 数据逻辑层:这里不直接涉及模板,但包含了获取列表数据的PHP代码,如 table_forum_forumdisplay.php(虽然名字是forumdisplay,但分类信息模块复用了很多其逻辑)。
/template/ - 模板根目录:这是存放所有模板文件的地方。
/template/你的默认模板目录/ - 具体模板文件目录:default、mobile 等,我们主要修改这里的文件。
最核心的模板文件是:
/template/你的默认模板目录/category/list.htm

这个文件是控制分类信息列表页主体结构和循环输出的核心。
模板文件结构详解 (list.htm)
打开 list.htm,你会发现它主要由 Discuz! 的模板标签(PHP代码)和HTML/CSS/JS构成,其结构通常如下:
{template common/header} <!-- 调用公共头部,如 <head>, <body>, 顶部导航等 -->
<!-- 页面主体内容区开始 -->
<div id="pt" class="bm cl">
<div class="z">
<a href="./" class="nvhm" title="{lang homepage}">$_G[setting][bbname]</a> <em>›</em>
{if $forum['ismoderator']}
<a href="forum.php?mod=moderate&fid=$_G[fid]">{lang moderate}</a> <em>›</em>
{/if}
<a href="forum.php?mod=list&fid=$_G[fid]">$_G[forum][name]</a>
</div>
</div>
<div id="ct" class="ct2 wp cl">
<!-- 左侧主要内容区 -->
<div class="mn">
<!-- 筛选和排序工具栏 -->
<div class="bm bw0 cl">
<!-- 这里是筛选条件,如地区、行业、价格等 -->
{subtemplate category/filter} <!-- 通常筛选器会调用一个子模板 -->
<!-- 这里是排序方式,如最新发布、价格排序等 -->
<div class="tb tb_h cl">
<div class="y">
<a href="javascript:;" onclick="setcookie('forumviewmode', 'table', 864000);location.reload();" {if !empty($_G['cookie']['forumviewmode']) && $_G['cookie']['forumviewmode'] == 'table'}class="a"{/if}>{lang table_view}</a>
<a href="javascript:;" onclick="setcookie('forumviewmode', 'list', 864000);location.reload();" {if empty($_G['cookie']['forumviewmode']) || $_G['cookie']['forumviewmode'] == 'list'}class="a"{/if}>{lang list_view}</a>
</div>
</div>
</div>
<!-- 信息列表主体 -->
<div class="bm">
<!-- 列表头部,显示总信息数等 -->
<div class="bm_h cl">
<span class="y">
<!-- 分页代码 -->
{if $multipage}
<div class="pgs cl">$multipage</div>
{/if}
</span>
<h2>{lang list_posts} ({$total})</h2>
</div>
<!-- 列表项循环区域 -->
<div class="bm_c">
<!-- 列表项的HTML结构,这里通常是一个表格或div列表 -->
<!-- {loop $list $var} ... {/loop} 是循环标签 -->
{loop $list $thread}
<table summary="forum_$thread[tid]" cellpadding="0" cellspacing="0" class="olt">
<tr>
<td class="icn">
<!-- 帖子图标、置顶、加精等标记 -->
{if $thread['typeid']}
<a href="forum.php?mod=list&fid=$_G[fid]&typeid=$thread[typeid]" target="_blank">
<img src="{STATICURL}image/common/type_$thread[typeid].gif" alt="$thread[typename]" />
</a>
{/if}
<a href="forum.php?mod=viewthread&tid=$thread[tid]" {if $thread[highlight]}class="$thread[highlight]"{/if} id="thread_title_$thread[tid]">
<!-- 这里是帖子的标题 -->
$thread[subject]
</a>
</td>
<td class="c">
<!-- 作者信息 -->
<a href="home.php?mod=space&uid=$thread[authorid]" c="1">$thread[author]</a>
<br />
<span class="xs">
<!-- 发布时间 -->
{echo dgmdate($thread[dateline], 'u')}
</span>
</td>
<td class="a">
<!-- 回复数/浏览数 -->
{if $thread[replies]}
<a href="forum.php?mod=viewthread&tid=$thread[tid]&page={$thread[pages]}&extra=page%3D1#lastpost">$thread[replies]</a>
{/if}
/ $thread[views]
</td>
</tr>
<!-- 如果启用了自定义字段,这里会循环显示 -->
{if $thread['fields']}
<tr>
<td colspan="3">
{loop $thread['fields'] $field}
<div class="cl">
<span class="y">{lang category:$field['title']}</span>
<span>$field[value]</span>
</div>
{/loop}
</td>
</tr>
{/if}
</table>
{/loop}
</div>
<!-- 列表底部,再次显示分页 -->
<div class="bm_b cl">
{if $multipage}
<div class="pgs cl">$multipage</div>
{/if}
</div>
</div>
</div>
<!-- 右侧边栏 -->
<div class="sd">
<!-- 这里可以调用其他子模板,如热门信息、最新信息、分类导航等 -->
{subtemplate category/right_sidebar} <!-- 这是一个示例,具体取决于模板设置 -->
</div>
</div>
{template common/footer} <!-- 调用公共底部,如版权信息、页脚导航等 -->
关键模板标签和数据
数据变量
这些变量通常由后台PHP代码 (source/class/table/...) 查询数据库后赋值给模板引擎。
$_G['forum']: 当前分类的信息,如名称、ID等。$list: 一个数组,包含了当前页所有信息帖子的数据,在{loop $list $thread}中,$thread就代表每一个帖子。$thread['tid']: 帖子ID。$thread['subject']: 帖子标题。$thread['author']: 帖子作者。$thread['authorid']: 帖子作者ID。$thread[dateline]: 帖子发布时间(时间戳)。$thread[replies]: 回复数。$thread[views]: 浏览数。$thread['typeid']: 帖子所属的分类ID(二级分类)。$thread['typename']: 帖子所属的分类名称。$thread['fields']: 非常重要! 这是帖子自定义字段的数组,如果你的分类信息有“价格”、“面积”、“联系电话”等字段,它们的数据就存在这里。$total: 当前分类下的信息总数。$multipage: 分页导航的HTML代码。
核心标签
{template common/header}/{template common/footer}: 公共头部和尾部。{loop $list $thread}/{/loop}: 循环标签,遍历$list数组,对每个帖子执行一次循环体内的代码。{subtemplate ...}: 调用子模板,筛选器、侧边栏等通常会拆分成独立的子模板文件,方便管理和复用。{lang ...}: 语言包标签,用于显示多语言支持的文本。{STATICURL}: 站点静态资源目录的URL。
常见修改与自定义
修改列表项的显示样式
最常见的需求是改变列表项的布局,默认是表格布局,你可以将其改为更现代的 div 布局。
示例:将表格改为卡片式布局
在 list.htm 的 {loop $list $thread} 部分,将 <table> 标签替换为 div。
<!-- 原始表格结构 -->
{loop $list $thread}
<table summary="forum_$thread[tid]" cellpadding="0" cellspacing="0" class="olt">
...
</table>
{/loop}
<!-- 修改为卡片式div结构 -->
{loop $list $thread}
<div class="info-card cl">
<div class="card-main">
<h3>
<a href="forum.php?mod=viewthread&tid=$thread[tid]">
$thread[subject]
</a>
</h3>
<div class="card-meta">
<span class="author">作者: <a href="home.php?mod=space&uid=$thread[authorid]">$thread[author]</a></span>
<span class="time">{echo dgmdate($thread[dateline], 'Y-m-d H:i')}</span>
</div>
<!-- 循环显示自定义字段 -->
{if $thread['fields']}
<div class="card-fields">
{loop $thread['fields'] $field}
<p><strong>{lang category:$field['title']}:</strong> $field[value]</p>
{/loop}
</div>
{/if}
</div>
<div class="card-stats">
<span>浏览: $thread[views]</span>
<span>回复: $thread[replies]</span>
</div>
</div>
{/loop}
在CSS文件(通常是 template/你的模板目录/css/common.css)中添加 .info-card, .card-main 等样式,即可实现美观的卡片效果。
调整筛选器
筛选器通常由一个子模板控制,category/filter.htm,你可以直接编辑这个文件来增删筛选条件,或者调整其样式和布局。
调整分页样式
分页的HTML代码由 $multipage 变量生成,这个变量是在PHP代码中生成的,如果你想彻底改变分页的样式,可能需要修改生成 $multipage 的PHP代码,或者用JavaScript来重新渲染它,但通常,通过CSS来美化 $multipage 生成的HTML结构是最简单的方法。
修改侧边栏
由 {subtemplate category/right_sidebar} 或类似标签调用,你可以编辑对应的子模板文件,或者直接在 list.htm 中写死HTML内容来添加你想要的模块,热门信息”、“最新发布”、“相关推荐”等。
调试与开发技巧
-
开启模板调试模式: 在
config/config_global.php文件中,找到$_G['debug'],将其设置为7。$_G['debug'] = 7;
这样,页面底部会显示当前使用的模板路径、加载的模板文件列表以及SQL查询语句,非常有助于排查问题。
-
使用浏览器开发者工具: 这是前端开发必备,右键 -> 检查,你可以实时查看HTML结构、修改CSS样式并立即看到效果,定位到对应的CSS类名后再去编辑CSS文件。
-
从默认模板开始修改: 如果你不确定自己的修改是否正确,建议先复制一份
default模板,命名为my_custom_template,然后对这个新模板进行修改,这样即使改坏了,也不会影响网站正在使用的模板。 -
理解模板继承: 一些模板框架(如Discuz! X3.5之后的某些版本)可能会引入类似
{template header}这样的继承机制,但Discuz!的核心仍然是文件包含,理解{template xxx}是将xxx.htm文件的内容原样插入到当前位置即可。
希望这份详细的解析能帮助你更好地理解和修改Discuz!分类信息列表页模板!
