You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

527 lines
16 KiB

<?php
/**
* About 页面导航区块
* 显示可自定义的导航菜单
*/
// 防止直接访问
if (!defined('ABSPATH')) {
exit;
}
// 获取短代码参数(如果通过短代码调用)
global $about_nav_shortcode_atts;
$shortcode_atts = (is_array($about_nav_shortcode_atts)) ? $about_nav_shortcode_atts : array();
// 配置类
if (!class_exists('AboutNavConfig')) {
class AboutNavConfig {
public $menu_id;
public $element_id;
public $css_class;
public function __construct($atts = array()) {
// 从短代码参数或自定义器获取设置
$this->menu_id = !empty($atts['menu_id']) ? $atts['menu_id'] : get_theme_mod('about_nav_menu_id', '');
$this->element_id = !empty($atts['id']) ? $atts['id'] : 'nenghui-about-nav';
$this->css_class = !empty($atts['class']) ? $atts['class'] : '';
}
public function get_menu_items() {
if (empty($this->menu_id)) {
return array();
}
// 验证菜单ID是否为有效的数字
$menu_id = intval($this->menu_id);
if ($menu_id <= 0) {
return array();
}
// 检查菜单是否存在
$menu = wp_get_nav_menu_object($menu_id);
if (!$menu || is_wp_error($menu)) {
return array();
}
// 获取菜单项
$menu_items = wp_get_nav_menu_items($menu_id);
if (!$menu_items || is_wp_error($menu_items) || !is_array($menu_items)) {
return array();
}
// 过滤掉无效的菜单项
$menu_items = array_filter($menu_items, function($item) {
return $item && !empty($item->title);
});
// 处理菜单项数据
$processed_items = array();
foreach ($menu_items as $item) {
$processed_items[] = array(
'id' => $item->ID,
'title' => $item->title,
'url' => $item->url,
'target' => $item->target,
'classes' => implode(' ', $item->classes),
'is_current' => $this->is_current_page($item->url)
);
}
return $processed_items;
}
private function is_current_page($url) {
// 安全地获取当前URL
$request_uri = isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : '';
if (empty($request_uri)) {
return false;
}
$current_url = home_url($request_uri);
$parsed_url = parse_url($url);
$parsed_current = parse_url($current_url);
// 确保解析结果是数组
if (!is_array($parsed_url) || !is_array($parsed_current)) {
return false;
}
// 比较路径
if (isset($parsed_url['path']) && isset($parsed_current['path'])) {
return rtrim($parsed_url['path'], '/') === rtrim($parsed_current['path'], '/');
}
return false;
}
}
}
// 初始化配置
$config = new AboutNavConfig($shortcode_atts);
$menu_items = $config->get_menu_items();
// 获取自定义器设置
$nav_bg_color = get_theme_mod('about_nav_bg_color', '#ffffff');
$nav_text_color = get_theme_mod('about_nav_text_color', '#333333');
$nav_active_color = get_theme_mod('about_nav_active_color', '#007cba');
$nav_style = get_theme_mod('about_nav_style', 'horizontal');
$nav_position = get_theme_mod('about_nav_position', 'top');
// 如果没有菜单项,显示提示信息
if (!is_array($menu_items) || empty($menu_items)) {
$debug_info = '';
if (defined('WP_DEBUG') && WP_DEBUG) {
// 获取所有可用菜单进行调试
$all_menus = wp_get_nav_menus();
$available_menus = array();
if (is_array($all_menus)) {
foreach ($all_menus as $menu) {
$available_menus[] = $menu->term_id . ':' . $menu->name;
}
}
$debug_info = '<br><small>调试信息: 当前菜单ID = ' . esc_html($config->menu_id) .
'<br>可用菜单: ' . esc_html(implode(', ', $available_menus)) . '</small>';
}
echo '<div class="about-nav-notice">请在自定义器中设置 About 导航菜单' . $debug_info . '</div>';
return;
}
?>
<nav id="<?php echo esc_attr($config->element_id); ?>"
class="about-nav-section nenghui-about-nav nav-<?php echo esc_attr($nav_style); ?> nav-position-<?php echo esc_attr($nav_position); ?> <?php echo esc_attr($config->css_class); ?>"
style="background-color: <?php echo esc_attr($nav_bg_color); ?>"
data-aos="fade-up">
<div class="about-nav-container" data-aos="fade-up" data-aos-delay="200">
<ul class="about-nav-menu" data-aos="fade-up" data-aos-delay="400">
<?php foreach ($menu_items as $item): ?>
<li class="about-nav-item <?php echo $item['is_current'] ? 'active' : ''; ?>">
<a href="<?php echo esc_url($item['url']); ?>"
class="about-nav-link <?php echo esc_attr($item['classes']); ?>"
style="color: <?php echo esc_attr($nav_text_color); ?>"
<?php echo !empty($item['target']) ? 'target="' . esc_attr($item['target']) . '"' : ''; ?>>
<?php echo esc_html($item['title']); ?>
</a>
</li>
<?php endforeach; ?>
</ul>
</div>
</nav>
<style>
/* About 导航区块样式 */
.nenghui-about-nav {
width: 100%;
border-bottom: 1px solid #eee;
position: relative;
z-index: 100;
}
.about-nav-container {
width: 80%;
max-width: 1200px;
margin: 0 auto;
padding: 0;
}
.about-nav-menu {
list-style: none;
margin: 0;
padding: 0;
display: flex;
align-items: center;
justify-content: center;
flex-wrap: wrap;
}
.about-nav-item {
margin: 0;
padding: 0;
position: relative;
}
.about-nav-link {
display: block;
padding: 20px 30px;
text-decoration: none;
font-size: 16px;
font-weight: 500;
transition: all 0.3s ease;
border-bottom: 3px solid transparent;
position: relative;
}
.about-nav-link:hover {
color: <?php echo esc_attr($nav_active_color); ?> !important;
text-decoration: none;
transition: all 0.3s ease;
}
.about-nav-item.active .about-nav-link {
color: <?php echo esc_attr($nav_active_color); ?> !important;
border-bottom-color: <?php echo esc_attr($nav_active_color); ?> !important;
}
/* 垂直样式 */
.nenghui-about-nav.nav-vertical .about-nav-menu {
flex-direction: column;
align-items: stretch;
}
.nenghui-about-nav.nav-vertical .about-nav-item {
width: 100%;
border-bottom: 1px solid #f0f0f0;
}
.nenghui-about-nav.nav-vertical .about-nav-item:last-child {
border-bottom: none;
}
.nenghui-about-nav.nav-vertical .about-nav-link {
border-bottom: none;
border-left: 3px solid transparent;
}
.nenghui-about-nav.nav-vertical .about-nav-item.active .about-nav-link {
border-left-color: <?php echo esc_attr($nav_active_color); ?> !important;
border-bottom-color: transparent !important;
background: rgba(0, 124, 186, 0.05);
}
/* 下拉菜单样式 */
.nenghui-about-nav.nav-dropdown {
position: relative;
}
.nenghui-about-nav.nav-dropdown .about-nav-menu {
position: relative;
}
.nenghui-about-nav.nav-dropdown .about-nav-item:hover .about-nav-submenu {
display: block;
}
/* 位置样式 */
.nenghui-about-nav.nav-position-top {
position: sticky;
top: 0;
}
.nenghui-about-nav.nav-position-sidebar {
position: fixed;
left: 0;
top: 50%;
transform: translateY(-50%);
width: auto;
border-bottom: none;
border-right: 1px solid #eee;
box-shadow: 2px 0 5px rgba(0,0,0,0.1);
}
.nenghui-about-nav.nav-position-sidebar .about-nav-container {
width: auto;
}
.nenghui-about-nav.nav-position-sidebar .about-nav-menu {
flex-direction: column;
}
.nenghui-about-nav.nav-position-bottom {
position: fixed;
bottom: 0;
left: 0;
right: 0;
border-top: 1px solid #eee;
border-bottom: none;
box-shadow: 0 -2px 5px rgba(0,0,0,0.1);
}
/* 响应式设计 */
@media (max-width: 768px) {
.about-nav-container {
width: 95%;
}
.about-nav-menu {
flex-direction: column;
align-items: stretch;
}
.about-nav-item {
width: 100%;
border-bottom: 1px solid #f0f0f0;
}
.about-nav-item:last-child {
border-bottom: none;
}
.about-nav-link {
padding: 15px 20px;
border-bottom: none;
border-left: 3px solid transparent;
}
.about-nav-item.active .about-nav-link {
border-left-color: #007cba;
border-bottom-color: transparent;
background: #f8f9fa;
}
}
@media (max-width: 480px) {
.about-nav-link {
padding: 12px 15px;
font-size: 14px;
}
}
/* 提示信息样式 */
.about-nav-notice {
padding: 20px;
text-align: center;
color: #666;
background: #f9f9f9;
border: 1px solid #ddd;
border-radius: 4px;
margin: 20px 0;
}
/* 加载动画 */
.nenghui-about-nav {
opacity: 0;
animation: fadeInNav 0.5s ease forwards;
}
@keyframes fadeInNav {
from {
opacity: 0;
transform: translateY(-10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
/* 高对比度模式支持 */
@media (prefers-contrast: high) {
.about-nav-link {
border-bottom-width: 2px;
}
.about-nav-item.active .about-nav-link {
border-bottom-width: 4px;
}
}
/* 减少动画模式支持 */
@media (prefers-reduced-motion: reduce) {
.about-nav-link {
transition: none;
}
.nenghui-about-nav {
animation: none;
opacity: 1;
}
}
</style>
<script>
// About 导航功能脚本
(function() {
'use strict';
// 等待 DOM 加载完成
document.addEventListener('DOMContentLoaded', function() {
const aboutNav = document.querySelector('.nenghui-about-nav');
if (!aboutNav) return;
// 平滑滚动到锚点
const navLinks = aboutNav.querySelectorAll('.about-nav-link');
navLinks.forEach(function(link) {
link.addEventListener('click', function(e) {
const href = this.getAttribute('href');
// 如果是锚点链接,添加平滑滚动
if (href && href.startsWith('#')) {
e.preventDefault();
const target = document.querySelector(href);
if (target) {
const offsetTop = target.offsetTop - aboutNav.offsetHeight - 20;
window.scrollTo({
top: offsetTop,
behavior: 'smooth'
});
// 更新活动状态
updateActiveState(this);
}
}
});
});
// 更新活动状态
function updateActiveState(activeLink) {
navLinks.forEach(function(link) {
link.parentElement.classList.remove('active');
});
activeLink.parentElement.classList.add('active');
}
// 滚动时更新活动状态(针对锚点导航)
let ticking = false;
function updateActiveOnScroll() {
if (!ticking) {
requestAnimationFrame(function() {
const scrollTop = window.pageYOffset;
const navHeight = aboutNav.offsetHeight;
navLinks.forEach(function(link) {
const href = link.getAttribute('href');
if (href && href.startsWith('#')) {
const target = document.querySelector(href);
if (target) {
const targetTop = target.offsetTop - navHeight - 50;
const targetBottom = targetTop + target.offsetHeight;
if (scrollTop >= targetTop && scrollTop < targetBottom) {
updateActiveState(link);
}
}
}
});
ticking = false;
});
ticking = true;
}
}
// 监听滚动事件
window.addEventListener('scroll', updateActiveOnScroll, { passive: true });
// 键盘导航支持
aboutNav.addEventListener('keydown', function(e) {
const focusedElement = document.activeElement;
const navItems = Array.from(aboutNav.querySelectorAll('.about-nav-link'));
const currentIndex = navItems.indexOf(focusedElement);
switch(e.key) {
case 'ArrowLeft':
case 'ArrowUp':
e.preventDefault();
const prevIndex = currentIndex > 0 ? currentIndex - 1 : navItems.length - 1;
navItems[prevIndex].focus();
break;
case 'ArrowRight':
case 'ArrowDown':
e.preventDefault();
const nextIndex = currentIndex < navItems.length - 1 ? currentIndex + 1 : 0;
navItems[nextIndex].focus();
break;
case 'Home':
e.preventDefault();
navItems[0].focus();
break;
case 'End':
e.preventDefault();
navItems[navItems.length - 1].focus();
break;
}
});
// 自定义器实时预览支持
if (typeof wp !== 'undefined' && wp.customize) {
// 监听背景色变化
wp.customize('about_nav_bg_color', function(value) {
value.bind(function(newval) {
aboutNav.style.backgroundColor = newval;
});
});
// 监听文字颜色变化
wp.customize('about_nav_text_color', function(value) {
value.bind(function(newval) {
navLinks.forEach(function(link) {
link.style.color = newval;
});
});
});
// 监听激活状态颜色变化
wp.customize('about_nav_active_color', function(value) {
value.bind(function(newval) {
// 更新 CSS 变量或直接更新样式
const activeLinks = aboutNav.querySelectorAll('.about-nav-item.active .about-nav-link');
activeLinks.forEach(function(link) {
link.style.color = newval;
link.style.borderBottomColor = newval;
});
});
});
// 监听样式变化
wp.customize('about_nav_style', function(value) {
value.bind(function(newval) {
aboutNav.className = aboutNav.className.replace(/nav-\w+/g, '');
aboutNav.classList.add('nav-' + newval);
});
});
// 监听位置变化
wp.customize('about_nav_position', function(value) {
value.bind(function(newval) {
aboutNav.className = aboutNav.className.replace(/nav-position-\w+/g, '');
aboutNav.classList.add('nav-position-' + newval);
});
});
}
});
})();
</script>