
PbootCMS作为一款国内主流的开源CMS系统,在细节决定用户体验的质量,经常发现精细的交互设计往往比华丽的外观更能提升用户满意度。今天我们将聚焦两个关键功能:智能导航高亮和自定义控制器的开发。
导航高亮是帮助用户清晰了解当前所在位置的重要视觉线索。在 PbootCMS 中,我们可以通过多种方式实现这一功能。
在 PbootCMS 模板文件中,最基本的导航高亮判断代码如下:
<nav class="main-nav">
<ul>
<li class="{pboot:if('[nav:scode]'=='{sort:scode}')}active{/pboot:if}">
<a href="{nav:link}">{nav:name}</a>
</li>
</ul>
</nav>这种方式的优点是简单直接,但缺点是只能精确匹配当前栏目,无法处理父栏目的高亮状态。
对于多级导航,我们需要更智能的高亮逻辑。以下代码可以同时处理当前栏目及其父级栏目的高亮:
<nav class="main-nav">
<ul>
{pboot:nav}
<li class="nav-item {pboot:if('[nav:scode]'=='{sort:scode}' || [nav:scode]=='{sort:topscode}')}active{/pboot:if} {pboot:if([nav:soncount]>0)}has-dropdown{/pboot:if}">
<a href="{nav:link}">{nav:name}</a>
{pboot:2if([nav:soncount]>0)}
<ul class="dropdown">
{pboot:nav parent=[nav:scode]}
<li class="{pboot:if('[nav:scode]'=='{sort:scode}')}active{/pboot:if}">
<a href="{nav:link}">{nav:name}</a>
</li>
{/pboot:nav}
</ul>
{/pboot:2if}
</li>
{/pboot:nav}
</ul>
</nav>此代码通过判断当前栏目的顶级栏目编号({sort:topscode})来实现父级导航的高亮,极大提升了导航的可用性。
首页通常需要特殊的高亮逻辑,因为它不属于任何栏目:
<nav class="main-nav">
<ul>
<li class="nav-item {pboot:if('{sort:scode}'=='')}active{/pboot:if}">
<a href="/">首页</a>
</li>
{pboot:nav}
<li class="nav-item {pboot:if('[nav:scode]'=='{sort:scode}' || [nav:scode]=='{sort:topscode}')}active{/pboot:if}">
<a href="{nav:link}">{nav:name}</a>
</li>
{/pboot:nav}
</ul>
</nav>这里通过判断 {sort:scode} 是否为空来识别首页,因为首页不会关联任何栏目编号。
PbootCMS 基于 ThinkPHP 的 MVC 架构,这意味着我们可以通过创建自定义控制器来扩展系统功能。
让我们创建一个处理导航数据的 API 控制器:
<?php
// 文件路径:/apps/home/controller/NavController.php
namespace app\home\controller;
use think\Controller;
use app\common\model\Nav;
use app\common\model\Content;
class NavController extends Controller
{
/**
* 获取增强导航数据(包含高亮状态)
* @return \think\Response
*/
public function enhancedNav()
{
// 获取当前栏目信息
$currentScode = request()->param('scode', '');
$currentTopScode = request()->param('topscode', '');
// 获取主导航
$navList = Nav::where('parent_id', 0)
->where('status', 1)
->order('sorting ASC, id ASC')
->select();
// 处理导航数据
$enhancedNav = [];
foreach ($navList as $nav) {
$navItem = $nav->toArray();
// 判断高亮状态
$navItem['is_active'] = $this->isNavActive($nav, $currentScode, $currentTopScode);
// 获取子导航
$navItem['children'] = Nav::where('parent_id', $nav['id'])
->where('status', 1)
->order('sorting ASC, id ASC')
->select()
->toArray();
// 处理子导航高亮
foreach ($navItem['children'] as &$child) {
$child['is_active'] = ($child['scode'] == $currentScode);
}
$enhancedNav[] = $navItem;
}
return json([
'code' => 200,
'data' => $enhancedNav,
'message' => '成功'
]);
}
/**
* 判断导航是否高亮
* @param object $nav 导航对象
* @param string $currentScode 当前栏目编号
* @param string $currentTopScode 当前顶级栏目编号
* @return bool
*/
private function isNavActive($nav, $currentScode, $currentTopScode)
{
// 直接匹配
if ($nav['scode'] == $currentScode) {
return true;
}
// 顶级栏目匹配
if ($nav['scode'] == $currentTopScode) {
return true;
}
// 首页特殊处理
if ($nav['link'] == '/' && empty($currentScode)) {
return true;
}
return false;
}
/**
* 获取面包屑导航
* @return \think\Response
*/
public function breadcrumb()
{
$scode = request()->param('scode', '');
$breadcrumbs = [];
// 首页面包屑
$breadcrumbs[] = ['name' => '首页', 'link' => '/'];
if (!empty($scode)) {
// 获取当前栏目信息
$currentNav = Nav::where('scode', $scode)
->where('status', 1)
->find();
if ($currentNav) {
// 获取父级栏目
if ($currentNav['parent_id'] > 0) {
$parentNav = Nav::find($currentNav['parent_id']);
if ($parentNav) {
$breadcrumbs[] = [
'name' => $parentNav['name'],
'link' => $parentNav['link']
];
}
}
$breadcrumbs[] = [
'name' => $currentNav['name'],
'link' => $currentNav['link']
];
}
}
return json([
'code' => 200,
'data' => $breadcrumbs,
'message' => '成功'
]);
}
}这个控制器提供了两个实用的API接口:enhancedNav 用于获取增强的导航数据(包含高亮状态),breadcrumb 用于生成面包屑导航。
要使自定义控制器正常工作,需要在路由配置文件中添加路由规则:
// 文件路径:/config/route.php
return [
// 默认路由规则
'nav/enhanced' => 'home/Nav/enhancedNav',
'nav/breadcrumb' => 'home/Nav/breadcrumb',
// 其他已有路由...
];在前端模板中,我们可以通过 AJAX 调用这些 API:
// 获取增强导航数据
fetch('/nav/enhanced?scode={sort:scode}&topscode={sort:topscode}')
.then(response => response.json())
.then(data => {
if (data.code === 200) {
this.renderNavigation(data.data);
}
})
.catch(error => console.error('导航数据加载失败:', error));
// 渲染导航
function renderNavigation(navData) {
let navHtml = '';
navData.forEach(nav => {
navHtml += `
<li class="nav-item ${nav.is_active ? 'active' : ''} ${nav.children.length > 0 ? 'has-dropdown' : ''}">
<a href="${nav.link}">${nav.name}</a>
${nav.children.length > 0 ? `
<ul class="dropdown">
${nav.children.map(child => `
<li class="${child.is_active ? 'active' : ''}">
<a href="${child.link}">${child.name}</a>
</li>
`).join('')}
</ul>
` : ''}
</li>
`;
});
document.querySelector('.main-nav ul').innerHTML = navHtml;
}频繁的导航数据查询会影响性能,我们可以加入缓存机制:
// 在 enhancedNav 方法中加入缓存
public function enhancedNav()
{
$currentScode = request()->param('scode', '');
$currentTopScode = request()->param('topscode', '');
$cacheKey = "enhanced_nav_{$currentScode}_{$currentTopScode}";
// 尝试从缓存获取
$cachedData = cache($cacheKey);
if ($cachedData) {
return json($cachedData);
}
// ... 原有逻辑 ...
$result = [
'code' => 200,
'data' => $enhancedNav,
'message' => '成功'
];
// 缓存结果(1小时)
cache($cacheKey, $result, 3600);
return json($result);
}为了让导航在不同模板中都能正常显示,我们可以创建通用的导航模板片段:
<!-- 文件路径:/template/default/includes/navigation.html -->
<nav class="main-nav">
<ul>
<li class="nav-item {pboot:if('{sort:scode}'=='')}active{/pboot:if}">
<a href="/">首页</a>
</li>
{pboot:nav}
<li class="nav-item {pboot:if('[nav:scode]'=='{sort:scode}' || [nav:scode]=='{sort:topscode}')}active{/pboot:if} {pboot:if([nav:soncount]>0)}has-dropdown{/pboot:if}">
<a href="{nav:link}">{nav:name}</a>
{pboot:2if([nav:soncount]>0)}
<ul class="dropdown">
{pboot:nav parent=[nav:scode]}
<li class="{pboot:if('[nav:scode]'=='{sort:scode}')}active{/pboot:if}">
<a href="{nav:link}">{nav:name}</a>
</li>
{/pboot:nav}
</ul>
{/pboot:2if}
</li>
{/pboot:nav}
</ul>
</nav>在其他模板中通过包含指令引入:
{include file='includes/navigation.html'}在开发过程中,调试是不可避免的环节。以下是几个实用技巧:
在 /config/config.php 中开启调试模式可以获取更详细的错误信息:
'debug' => true,使用浏览器开发者工具(F12)检查元素和网络请求,确保导航高亮的 CSS 类正确应用,API 接口正常返回数据。
修改模板或控制器后,务必清空缓存以确保更改生效:
后台管理 > 工具 > 清空整站缓存原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。