不修改核心文件,通过自定义模型、利用织梦的附加表和自定义表单功能,并结合jQuery和AJAX技术,实现一个美观、流畅、不刷新页面的筛选效果。

下面我将分步为你讲解整个过程,从最基础的“伪静态”方案到更高级的“AJAX”方案。
第一步:准备工作 - 创建筛选模型
这是实现筛选功能最关键的一步,我们需要一个地方来存储筛选条件,并且这个条件要与文章关联。
最佳实践:使用“自定义模型”和“附加表”
-
创建自定义模型
(图片来源网络,侵删)- 登录织梦后台 -> 核心 -> 内容模型管理 -> [添加新模型]
- 模型名称:
筛选模型(可以自定义) - 模型表前缀:
dede_sfilter_(前缀建议自定义,避免冲突) - 其他选项根据需要填写,然后提交。
-
为模型添加字段
- 进入刚刚创建的“筛选模型”的“字段管理”。
- 我们需要添加几个字段来代表筛选条件,
价格区间、品牌、颜色。 - 字段名称:
price_range(英文,用于数据库) - :
价格区间(中文,用于后台显示) - 字段类型:单选按钮 或 下拉框 (推荐,因为筛选条件通常是固定的)
- 选项值:
0-100元,100-500元,500-1000元,1000元以上(用英文逗号分隔) - 是否为前台投稿使用:根据需要选择。
- 是否显示在列表页:勾选,这样我们才能在列表页获取到这些值。
- 重复此步骤,为
brand(品牌) 和color(颜色) 等字段添加。
-
为文章附加筛选字段
- 进入后台 -> 核心 -> 频道管理 -> 选择你的文章栏目 (产品”)。
- 点击“修改”,在“内容模型”部分,选择你刚刚创建的“筛选模型”。
- 保存。
-
更新文章并填写筛选条件
- 现在去发布一篇新文章,你会发现除了常规内容,多出了“价格区间”、“品牌”等字段。
- 发布几篇测试文章,并为它们填写不同的筛选条件。
- 文章A:价格区间 =
0-100元,品牌 =品牌A - 文章B:价格区间 =
100-500元,品牌 =品牌A - 文章C:价格区间 =
0-100元,品牌 =品牌B
- 文章A:价格区间 =
至此,数据准备工作就完成了,你的文章数据已经通过附加表与筛选条件关联起来了。

第二步:前端页面实现
现在我们要在前台模板文件中,把这些筛选条件变成下拉框,并实现筛选逻辑。
我们以 list_article.htm (文章列表页模板) 为例。
伪静态/GET参数筛选 (简单,但会刷新页面)
这种方法最简单,直接利用织梦自带的URL参数。
-
在列表页添加筛选表单 在
list_article.htm的合适位置(head标签内或列表上方)添加以下HTML代码:<div class="filter-box"> <form name="search" action="{dede:global.cfg_cmspath/}/plus/list.php" method="get"> <input type="hidden" name="tid" value="{dede:field name='id'/}"> <!-- 价格区间筛选 --> <select name="price_range" onchange="document.search.submit();"> <option value="">全部价格</option> {dede:sql sql="SELECT DISTINCT price_range FROM `dede_sfilter_arctiny` WHERE price_range != '' AND typeid = ~typeid~"} <option value="[field:price_range/]" [field:price_range function='(@me == $_GET["price_range"] ? "selected" : "")'/]>[field:price_range/]</option> {/dede:sql} </select> <!-- 品牌筛选 --> <select name="brand" onchange="document.search.submit();"> <option value="">全部品牌</option> {dede:sql sql="SELECT DISTINCT brand FROM `dede_sfilter_arctiny` WHERE brand != '' AND typeid = ~typeid~"} <option value="[field:brand/]" [field:brand function='(@me == $_GET["brand"] ? "selected" : "")'/]>[field:brand/]</option> {/dede:sql} </select> <!-- 颜色筛选 --> <select name="color" onchange="document.search.submit();"> <option value="">全部颜色</option> {dede:sql sql="SELECT DISTINCT color FROM `dede_sfilter_arctiny` WHERE color != '' AND typeid = ~typeid~"} <option value="[field:color/]" [field:color function='(@me == $_GET["color"] ? "selected" : "")'/]>[field:color/]</option> {/dede:sql} </select> </form> </div>代码解释:
form的action指向织梦的列表处理文件list.php。name="tid"是必须的,告诉织梦要显示哪个栏目的文章。select的name属性要和数据库字段名一致,这样织梦才能识别。{dede:sql}自定义标签用来从附加表中查询出当前栏目下所有不重复的筛选选项。~typeid~是一个占位符,我们需要在模板文件顶部用PHP代码替换它。
-
修改模板文件,替换占位符 在
list_article.htm的最顶部,{dede:include filename="head.htm"/}之前,添加PHP代码:{dede:php} $typeid = isset($typeid) ? $typeid : 0; $this->Fields['typeid'] = $typeid; {/dede:php}这样,
{dede:sql}中的~typeid~就会被替换成当前栏目的ID。 -
织梦自动处理 当你选择一个选项并提交表单时,URL会变成类似
.../list.php?tid=1&price_range=0-100元&brand=品牌A的形式,织梦的list.php会自动解析这些参数,并生成相应的SQL查询,最终筛选出符合条件的文章列表。
优点:实现简单,无需复杂代码。 缺点:每次筛选都会刷新整个页面,用户体验不佳。
AJAX无刷新筛选 (推荐,用户体验好)
这种方法结合了jQuery和织梦的API,实现不刷新页面即可筛选。
-
引入jQuery库 在
list_article.htm的<head>标签内引入jQuery库:<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
-
修改筛选表单 将之前的表单修改为AJAX提交形式:
<div class="filter-box"> <!-- 价格区间筛选 --> <select id="price_range" name="price_range"> <option value="">全部价格</option> {dede:sql sql="SELECT DISTINCT price_range FROM `dede_sfilter_arctiny` WHERE price_range != '' AND typeid = ~typeid~"} <option value="[field:price_range/]">[field:price_range/]</option> {/dede:sql} </select> <!-- 品牌筛选 --> <select id="brand" name="brand"> <option value="">全部品牌</option> {dede:sql sql="SELECT DISTINCT brand FROM `dede_sfilter_arctiny` WHERE brand != '' AND typeid = ~typeid~"} <option value="[field:brand/]">[field:brand/]</option> {/dede:sql} </select> <!-- 颜色筛选 --> <select id="color" name="color"> <option value="">全部颜色</option> {dede:sql sql="SELECT DISTINCT color FROM `dede_sfilter_arctiny` WHERE color != '' AND typeid = ~typeid~"} <option value="[field:color/]">[field:color/]</option> {/dede:sql} </select> <button id="filter-btn">筛选</button> </div> <!-- 用于存放AJAX返回的文章列表 --> <div id="article-list"> {dede:list pagesize='10'} <li><a href="[field:arcurl/]">[field:title/]</a></li> {/dede:list} </div> -
编写AJAX和PHP处理代码 在模板文件底部,
</body>标签之前,添加以下代码:<script type="text/javascript"> $(document).ready(function(){ // 当筛选条件改变时,可以自动触发,也可以点击按钮触发 // 这里我们采用点击按钮触发的方式 $("#filter-btn").click(function(){ // 获取所有筛选条件的值 var tid = "{dede:field name='id'/}"; // 当前栏目ID var price_range = $("#price_range").val(); var brand = $("#brand").val(); var color = $("#color").val(); // 组装AJAX请求参数 var data = { 'tid': tid, 'price_range': price_range, 'brand': brand, 'color': color, 'ajax': 1 // 标记这是一个AJAX请求 }; // 发送AJAX请求 $.ajax({ url: "{dede:global.cfg_cmspath/}/plus/list.php", type: "GET", data: data, dataType: "html", success: function(response){ // 将返回的HTML内容替换到页面中 $("#article-list").html(response); }, error: function(){ alert("筛选失败,请稍后重试!"); } }); }); // 可选:当选择框改变时自动触发筛选 // $("#price_range, #brand, #color").change(function(){ // $("#filter-btn").click(); // }); }); </script> -
修改
list.php文件 (关键步骤) 为了让list.php能识别AJAX请求并返回纯HTML列表,我们需要修改它。 注意:修改核心文件前务必备份!打开
/plus/list.php文件,找到类似这样的代码段(通常在文件末尾):// ... // 解析模板,显示页面 $pv->ParseTemplets(); $pv->Display();
在这之前,添加以下判断代码:
// 判断是否为AJAX请求 if (isset($_GET['ajax']) && $_GET['ajax'] == 1) { // 只加载列表部分,不加载页面框架 // 这里直接调用列表标签的解析逻辑 $typeid = isset($_GET['tid']) ? intval($_GET['tid']) : 0; // 如果有其他筛选条件,在这里手动构建SQL WHERE子句 // 注意:为了安全,要对用户输入进行过滤和验证! $addQuery = " WHERE 1=1 "; if (!empty($_GET['price_range'])) { $addQuery .= " AND arc.addtable LIKE '%sfilter_arctiny%' AND a.price_range = '" . addslashes($_GET['price_range']) . "' "; } if (!empty($_GET['brand'])) { $addQuery .= " AND arc.addtable LIKE '%sfilter_arctiny%' AND a.brand = '" . addslashes($_GET['brand']) . "' "; } // ... 其他筛选条件 // 临时修改全局变量,让列表标签能识别我们的筛选条件 // 这是一个简化的示例,更健壮的方式是直接重写查询逻辑 // 这里为了演示方便,直接修改了全局变量,实际项目中应更严谨 if (!empty($addQuery)) { $GLOBALS['addSql'] = $addQuery; } // 调用列表标签 include(DEDETEMPLATE.'/default/list_article_ajax.htm'); // 注意:这里我们创建一个新的模板文件 exit; // 结束脚本,不执行下面的Display() } -
创建AJAX专用的列表模板 在你的模板目录下(
/templets/default/),创建一个新文件list_article_ajax.htm。这个文件只包含文章列表的HTML结构,不要包含
head、header、footer等页面框架。{dede:list pagesize='10'} <li><a href="[field:arcurl/]">[field:title/]</a></li> {/dede:list} <!-- 如果需要分页,也要在这里加上 --> <div class="page"> {dede:pagelist listitem='info,index,end,pre,next,option' listsize='5'/} </div>
优点:用户体验流畅,无需页面刷新,交互感强。 缺点:需要修改核心文件,对PHP和jQuery有一定要求,代码相对复杂。
总结与建议
| 特性 | 方案一 (伪静态) | 方案二 (AJAX) |
|---|---|---|
| 实现难度 | 低 | 中 |
| 用户体验 | 一般 (页面刷新) | 优秀 (无刷新) |
| 是否改核心 | 否 | 是 |
| 推荐度 | ⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
对于大多数网站,我强烈推荐你使用方案二(AJAX无刷新筛选),虽然前期需要多做一些工作,但它带来的用户体验提升是巨大的,也更符合现代网站的设计标准。
重要提示:
- 备份数据:在进行任何操作,特别是修改核心文件之前,请务必备份数据库和网站文件。
- SQL注入:在处理AJAX传来的参数时,一定要使用
addslashes()或更安全的预处理语句来防止SQL注入攻击。 - 性能:如果文章和筛选数据量非常大,频繁的AJAX请求可能会对服务器造成压力,可以考虑加入适当的缓存机制。
