如果分类比较多的话,我们在使用wordpress自带的产品分类添加到菜单中的时候会经常发现有些二级三级分类目录显示平铺,没有办法准确的找到对应的二级三级类目,因此本功能就产生了。
// 添加新的产品分类面板
function add_hierarchical_product_categories_meta_box() {
add_meta_box(
'hierarchical-product-cat',
'Product Categories Hierarchy',
'display_hierarchical_product_cat',
'nav-menus',
'side',
'low'
);
}
add_action('admin_init', 'add_hierarchical_product_categories_meta_box');
// 显示分类层级的回调函数
function display_hierarchical_product_cat() {
global $nav_menu_selected_id;
// 获取所有产品分类
$categories = get_terms([
'taxonomy' => 'product_cat',
'hide_empty' => false,
'hierarchical' => true,
'orderby' => 'name'
]);
// 构建分类层级树
$hierarchy = array();
foreach ($categories as $cat) {
if ($cat->parent == 0) {
$hierarchy[$cat->term_id] = $cat;
$hierarchy[$cat->term_id]->children = get_product_cat_children($cat->term_id, $categories);
}
}
?>
<div id="hierarchical-product-cat-wrap" class="taxonomydiv">
<ul class="taxonomy-tabs add-menu-item-tabs">
<li><a class="nav-tab-link" href="#tabs-panel-hierarchical-product-cat-all">View All</a></li>
<li><a class="nav-tab-link" href="#tabs-panel-hierarchical-product-cat-search">Search</a></li>
</ul>
<div id="tabs-panel-hierarchical-product-cat-all" class="tabs-panel tabs-panel-view-all tabs-panel-active">
<ul class="categorychecklist form-no-clear">
<?php display_product_cat_tree($hierarchy); ?>
</ul>
</div>
<div id="tabs-panel-hierarchical-product-cat-search" class="tabs-panel tabs-panel-search">
<p><input type="text" class="quick-search" placeholder="Search categories"></p>
<span class="spinner"></span>
<ul class="categorychecklist form-no-clear"></ul>
</div>
<p class="button-controls wp-clearfix">
<span class="list-controls hide-if-no-js">
<input type="checkbox" id="hierarchical-product-cat-select-all" class="select-all">
<label for="hierarchical-product-cat-select-all">Select All</label>
</span>
<span class="add-to-menu">
<input type="submit" class="button submit-add-to-menu right" value="Add to Menu" name="add-hierarchical-product-cat-menu-item" id="submit-hierarchical-product-cat">
<span class="spinner"></span>
</span>
</p>
</div>
<script>
jQuery(document).ready(function($) {
var $container = $('#hierarchical-product-cat-wrap');
// 标签切换
$container.on('click', '.nav-tab-link', function(e) {
e.preventDefault();
var $link = $(this);
var panel = $link.attr('href');
$('.tabs-panel', $container).hide();
$(panel).show();
});
// 处理分类选择
function handleCategorySelection($checkbox) {
var isChecked = $checkbox.prop('checked');
var $li = $checkbox.closest('li');
$li.find('> ul.children input[type="checkbox"]').prop('checked', isChecked);
if (!isChecked) {
$li.parents('li').each(function() {
$(this).find('> label input[type="checkbox"]').prop('checked', false);
});
} else {
var $siblings = $li.siblings('li');
var allChecked = true;
$siblings.add($li).each(function() {
if (!$(this).find('> label input[type="checkbox"]').prop('checked')) {
allChecked = false;
return false;
}
});
if (allChecked) {
var $parent = $li.parent().closest('li');
if ($parent.length) {
$parent.find('> label input[type="checkbox"]').prop('checked', true);
}
}
}
}
// 复选框事件
$container.on('change', 'input[type="checkbox"]', function() {
if ($(this).hasClass('select-all')) {
$('.categorychecklist input[type="checkbox"]', $container).prop('checked', this.checked);
} else {
handleCategorySelection($(this));
}
});
// 搜索功能
var searchTimeout;
$('.quick-search', $container).on('keyup', function() {
var searchValue = $(this).val().toLowerCase();
clearTimeout(searchTimeout);
searchTimeout = setTimeout(function() {
$('#tabs-panel-hierarchical-product-cat-all li').each(function() {
var $item = $(this);
var text = $item.find('> label').text().toLowerCase();
if (text.indexOf(searchValue) > -1) {
$item.show();
$item.parents('li').show();
} else {
$item.hide();
}
});
}, 300);
});
// 在 script 标签内,修改"添加到菜单"部分的代码:
$('#submit-hierarchical-product-cat').on('click', function(e) {
e.preventDefault();
var $checked = $('.categorychecklist input:checked', $container);
if (!$checked.length) return;
var $submitButton = $(this);
var $spinner = $submitButton.next('.spinner');
$submitButton.prop('disabled', true);
$spinner.addClass('is-active');
var menuItems = {};
$checked.each(function(i) {
var $item = $(this);
var $li = $item.closest('li');
var termId = $item.val();
var title = $li.find('> label').text().trim();
// 获取父级ID
var parentId = 0;
var $parentLi = $li.parents('li').first();
if ($parentLi.length) {
var $parentCheckbox = $parentLi.find('> label input[type="checkbox"]');
if ($parentCheckbox.length && $parentCheckbox.prop('checked')) {
parentId = -1 - $checked.index($parentCheckbox);
}
}
var key = 'menu-item[' + (-1 - i) + ']';
menuItems[key + '[menu-item-title]'] = title;
menuItems[key + '[menu-item-type]'] = 'taxonomy';
menuItems[key + '[menu-item-object]'] = 'product_cat';
menuItems[key + '[menu-item-object-id]'] = termId;
menuItems[key + '[menu-item-db-id]'] = 0;
menuItems[key + '[menu-item-parent-id]'] = parentId;
menuItems[key + '[menu-item-position]'] = i;
});
var data = $.extend({
'action': 'add-menu-item',
'menu': $('#menu').val(),
'menu-settings-column-nonce': $('#menu-settings-column-nonce').val()
}, menuItems);
$.post(ajaxurl, data, function(response) {
if (response && response.length > 0) {
$(response).each(function() {
$('#menu-to-edit').append(this);
});
wpNavMenu.refreshKeyboardAccessibility();
wpNavMenu.refreshAdvancedAccessibility();
wpNavMenu.registerChange();
}
$checked.prop('checked', false);
$('#hierarchical-product-cat-select-all').prop('checked', false);
})
.always(function() {
$submitButton.prop('disabled', false);
$spinner.removeClass('is-active');
});
});
});
</script>
<?php
}
// 获取子分类
function get_product_cat_children($parent_id, $categories) {
$children = array();
foreach ($categories as $cat) {
if ($cat->parent == $parent_id) {
$cat->children = get_product_cat_children($cat->term_id, $categories);
$children[] = $cat;
}
}
return $children;
}
// 修改 display_product_cat_tree 函数
function display_product_cat_tree($categories, $depth = 0) {
foreach ($categories as $cat) {
$term_link = get_term_link($cat->term_id, 'product_cat');
if (!is_wp_error($term_link)) {
?>
<li data-term-id="<?php echo esc_attr($cat->term_id); ?>"
<?php if ($cat->parent) echo 'data-parent-id="' . esc_attr($cat->parent) . '"'; ?>>
<label class="menu-item-title">
<input type="checkbox"
class="menu-item-checkbox"
value="<?php echo esc_attr($cat->term_id); ?>">
<?php echo esc_html($cat->name); ?>
<input type="hidden" class="menu-item-url" value="<?php echo esc_url($term_link); ?>">
<?php if ($cat->parent): ?>
<input type="hidden" class="menu-item-parent-id" value="<?php echo esc_attr($cat->parent); ?>">
<?php endif; ?>
</label>
<?php if (!empty($cat->children)): ?>
<ul class="children">
<?php display_product_cat_tree($cat->children, $depth + 1); ?>
</ul>
<?php endif; ?>
</li>
<?php
}
}
}
这个完整实现提供了:
- 核心功能:
- 层级显示
- 父子联动选择
- 搜索筛选
- 添加到菜单
- 用户界面:
- 清晰的视觉层级
- 响应式设计
- 加载状态提示
- 错误处理
- 交互优化:
- 全选功能
- 实时搜索
- 平滑过渡
- 直观操作
使用方法:
- 将代码复制到主题的functions.php文件中
- 刷新菜单编辑页面
- 在左侧可以看到新的”Product Categories Hierarchy”面板
需要注意:
- 确保WooCommerce已经安装并激活
- 需要有产品分类数据
- 需要适当的用户权限