首页 > 其他分享 >WordPress产品分类添加,自动排序插件

WordPress产品分类添加,自动排序插件

时间:2024-09-29 14:12:03浏览次数:9  
标签:cmo 插件 菜单 menu item WordPress items 排序 id

效果图如下

 

 

目前这个预览菜单这个效果有点问题,但是不影响实际排序,有懂源码的朋友可以自行修改一下,
目录结构
menu
  -assets
    menu.css

    menu.js

  menu.php  

源码如下
menu.php文件

<?php
/**
 * Plugin Name: 菜单整理
 * Description: 将 WooCommerce 产品分类添加到现有菜单中。
 * Version: 1.2
 * Author: 朵啦
 * License: GPL2
 */

// 防止直接访问文件
if (!defined('ABSPATH')) {
    exit;
}

// 注册插件设置页面
add_action('admin_menu', 'cmo_add_admin_menu');
function cmo_add_admin_menu() {
    add_menu_page(
        '分类菜单管理',      // 页面标题
        '分类菜单',          // 菜单标题
        'manage_options',    // 权限
        'cmo-settings',      // 菜单 slug
        'cmo_settings_page', // 回调函数
        'dashicons-menu',    // 图标
        60                   // 位置
    );
}

// 引入 JS 和 CSS 文件
add_action('admin_enqueue_scripts', 'cmo_enqueue_scripts');
function cmo_enqueue_scripts() {
    wp_enqueue_script('cmo-menu-js', plugin_dir_url(__FILE__) . 'assets/menu.js', ['jquery'], false, true);
    wp_enqueue_style('cmo-menu-css', plugin_dir_url(__FILE__) . 'assets/menu.css');
}

// 使 ajaxurl 变量在前端 JavaScript 中可用
add_action('admin_enqueue_scripts', 'add_ajax_url');
function add_ajax_url() {
    wp_localize_script('cmo-menu-js', 'ajaxurl', admin_url('admin-ajax.php'));
}

// 设置页面的显示内容
function cmo_settings_page() {
    ?>
    <div class="wrap">
        <h1>WooCommerce 分类菜单管理</h1>
        <form method="post" action="options.php">
            <?php
            settings_fields('cmo_settings_group');
            
            function cmo_section_text() {
                echo '<p>选择要添加到菜单的产品分类</p>';
            }

            do_settings_sections('cmo-settings');
            
            ?>
        </form>

        <h2>菜单操作</h2>
        <form method="post" action="" id="menu-action-form">
            <label for="cmo_menu_selector">选择菜单:</label>
            <?php cmo_menu_selector(); ?>
            <button type="button" id="cmo_add_to_menu" class="button button-primary">添加分类到选定菜单</button>
            <button type="button" id="cmo_backup_menu" class="button">备份当前菜单</button>
            <button type="button" id="cmo_restore_menu" class="button">恢复备份菜单</button>
        </form>

        <div id="menu-preview">
            <h3>菜单预览</h3>
            <div id="preview-content"></div>
        </div>
    </div>
    <?php
}

// 注册设置字段
add_action('admin_init', 'cmo_settings_init');
function cmo_settings_init() {
    register_setting('cmo_settings_group', 'cmo_selected_categories');

    add_settings_section(
        'cmo_main_section', 
        '选择要添加到菜单的产品分类', 
        'cmo_section_text', 
        'cmo-settings'
    );

    add_settings_field(
        'cmo_categories_field', 
        '产品分类', 
        'cmo_categories_field_callback', 
        'cmo-settings', 
        'cmo_main_section'
    );
}

// 分类选择字段回调,递归展示分类
function cmo_categories_field_callback($parent = 0, $level = 0) {
    if ($parent == 0 || $level == 0) {
        // 只在最顶层展示全选按钮
        echo '<input type="checkbox" id="select-all"> 全选<br><div style="display: flex; flex-wrap: wrap;">';
    }

    $categories = get_terms([
        'taxonomy' => 'product_cat',
        'hide_empty' => false,
        'parent' => $parent // 通过 parent 参数递归获取子分类
    ]);

    $selected_categories = get_option('cmo_selected_categories', []);

    if (!is_array($selected_categories)) {
        $selected_categories = [];
    }

    foreach ($categories as $category) {
        // 缩进效果,表示分类层级
        $indent = str_repeat('   ', $level);

        echo '<div style="flex-basis: 100%; margin-left:' . ($level * 20) . 'px;">' . 
            '<input type="checkbox" name="cmo_selected_categories[]" value="' . esc_attr($category->term_id) . '" ' .
            checked(in_array($category->term_id, $selected_categories), true, false) . '> ' . esc_html($category->name) . '</div>';

        // 递归调用自己,展示子分类
        cmo_categories_field_callback($category->term_id, $level + 1);
    }

    if ($parent == 0 && $level == 0) {
        // 结束顶层div
        echo '</div>';
    }
}

// 生成分类菜单选择器
function cmo_menu_selector() {
    $menus = wp_get_nav_menus();
    echo '<select name="cmo_selected_menu" id="cmo_menu_selector">';
    foreach ($menus as $menu) {
        echo '<option value="' . esc_attr($menu->term_id) . '">' . esc_html($menu->name) . '</option>';
    }
    echo '</select>';
}

// 添加分类到菜单的功能
add_action('wp_ajax_cmo_add_to_menu', 'cmo_add_categories_to_menu');
function cmo_add_categories_to_menu() {
    if (!isset($_POST['menu_id'])) {
        wp_send_json_error('菜单ID未设置');
    }

    $menu_id = intval($_POST['menu_id']);
    
    if (!isset($_POST['selected_categories']) || empty($_POST['selected_categories'])) {
        wp_send_json_error('未选择任何分类');
    }

    $selected_categories = $_POST['selected_categories'];
    
    // 创建一个数组来保存分类和菜单项的 ID 关联
    $category_menu_items = [];

    // 循环处理选中的分类
    foreach ($selected_categories as $category_id) {
        $category = get_term($category_id, 'product_cat');
        
        // 获取当前分类的父分类 ID
        $parent_id = $category->parent;
        
        // 如果父分类已存在菜单项,则将其设置为子菜单项
        $parent_menu_item_id = isset($category_menu_items[$parent_id]) ? $category_menu_items[$parent_id] : 0;

        // 添加菜单项,并保存它的 ID
        $menu_item_id = wp_update_nav_menu_item($menu_id, 0, [
            'menu-item-title' => esc_html($category->name),
            'menu-item-url' => get_term_link($category),
            'menu-item-status' => 'publish',
            'menu-item-parent-id' => $parent_menu_item_id, // 指定父菜单项
        ]);

        // 将当前分类的菜单项 ID 保存到数组中,供子分类使用
        $category_menu_items[$category_id] = $menu_item_id;
    }

    wp_send_json_success('分类已成功添加到菜单');
}

// 备份当前菜单
add_action('wp_ajax_cmo_backup_menu', 'cmo_backup_menu');
function cmo_backup_menu() {
    if (!isset($_POST['menu_id'])) {
        wp_send_json_error('菜单ID未设置');
    }

    $menu_id = intval($_POST['menu_id']);
    $menu_items = wp_get_nav_menu_items($menu_id);

    if ($menu_items) {
        update_option('cmo_menu_backup_' . $menu_id, $menu_items);
        wp_send_json_success('菜单已成功备份');
    }

    wp_send_json_error('备份失败');
}

// 恢复备份菜单
add_action('wp_ajax_cmo_restore_menu', 'cmo_restore_menu');
function cmo_restore_menu() {
    if (!isset($_POST['menu_id'])) {
        wp_send_json_error('菜单ID未设置');
    }

    $menu_id = intval($_POST['menu_id']);
    $backup = get_option('cmo_menu_backup_' . $menu_id);

    if ($backup) {
        foreach ($backup as $item) {
            wp_update_nav_menu_item($menu_id, 0, [
                'menu-item-title' => esc_html($item->title),
                'menu-item-url' => $item->url,
                'menu-item-status' => 'publish',
            ]);
        }
        wp_send_json_success('菜单已成功恢复');
    }

    wp_send_json_error('没有备份可恢复');
}

// 预览菜单内容
add_action('wp_ajax_cmo_preview_menu', 'cmo_preview_menu');
function cmo_preview_menu() {
    if (!isset($_POST['menu_id'])) {
        wp_send_json_error('菜单ID未设置');
    }

    $menu_id = intval($_POST['menu_id']);
    $menu_items = wp_get_nav_menu_items($menu_id);

    if (empty($menu_items)) {
        wp_send_json_error('该菜单没有内容');
    }

    $html = '<ul class="menu-preview">';

    foreach ($menu_items as $item) {
        // 根据菜单项的 parent 判断是否是子项
        if ($item->menu_item_parent == 0) {
            $html .= '<li class="menu-item">' . esc_html($item->title);
            
            // 查找子项
            $html .= get_menu_child_items($menu_items, $item->ID);
            $html .= '</li>';
        }
    }

    $html .= '</ul>';

    wp_send_json_success($html);
}

// 获取子菜单项的递归函数
function get_menu_child_items($menu_items, $parent_id) {
    $child_items = '';
    foreach ($menu_items as $item) {
        if ($item->menu_item_parent == $parent_id) {
            if ($child_items == '') {
                $child_items .= '<ul class="submenu">';
            }
            $child_items .= '<li class="menu-item">' . esc_html($item->title);
            $child_items .= get_menu_child_items($menu_items, $item->ID);
            $child_items .= '</li>';
        }
    }
    if ($child_items != '') {
        $child_items .= '</ul>';
    }
    return $child_items;
}


?>

  

menu.css文件

/* 调整预览框的高度和宽度 */
#menu-preview {
    margin-top: 20px;
    border: 1px solid #ddd;
    padding: 10px;
    background-color: #f9f9f9;
    width: 100%; /* 让框的宽度适应容器 */
    height: 400px; /* 设置高度为400px,具体可根据需要调整 */
    overflow-y: auto; /* 让框的内容可以滚动 */
    box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1); /* 添加阴影效果 */
}

/* 一级菜单样式 */
.menu-preview {
    display: flex;
    flex-direction: row;
    list-style: none;
    padding: 0;
    margin: 0;
}

.menu-item {
    position: relative;
    padding: 10px 20px;
    background-color: #f0f0f0;
    margin-right: 10px;
    cursor: default;
    border: 1px solid #ccc; /* 添加边框 */
    border-radius: 5px; /* 圆角效果 */
    font-weight: bold; /* 让文字加粗 */
    transition: background-color 0.3s ease; /* 添加背景颜色的过渡效果 */
}

/* 一级菜单悬浮效果 */
.menu-item:hover {
    background-color: #e0e0e0;
    border-color: #b0b0b0; /* 悬浮时改变边框颜色 */
}

/* 子菜单样式 */
.submenu {
    display: none;
    position: absolute;
    top: 100%;
    left: 0;
    background-color: white;
    list-style: none;
    padding: 0;
    margin: 0;
    box-shadow: 0 8px 16px rgba(0, 0, 0, 0.1);
    z-index: 10; /* 确保子菜单在顶层显示 */
    opacity: 0; /* 初始透明度 */
    visibility: hidden; /* 初始不可见 */
    transition: opacity 0.3s ease, visibility 0.3s ease; /* 过渡效果 */
}

/* 子菜单项的样式 */
.submenu .menu-item {
    padding: 10px;
    margin-right: 0;
    white-space: nowrap;
    background-color: #ffffff;
    border: 1px solid #ddd; /* 给子菜单项添加边框 */
    border-radius: 3px;
}

/* 子菜单项的悬浮效果 */
.submenu .menu-item:hover {
    background-color: #f0f0f0;
}

/* 一级菜单悬浮时显示子菜单 */
.menu-item:hover .submenu {
    display: block;
    opacity: 1; /* 显示时渐变透明度 */
    visibility: visible; /* 显示可见 */
    z-index: 999;
}

/* 让一级菜单项和子菜单保持距离 */
.menu-item:hover .submenu {
    margin-top: 5px;
}

/* 调整子菜单的位置 */
.submenu {
    min-width: 200px; /* 给子菜单设置最小宽度 */
    z-index: 1000;
}

/* 鼠标移开子菜单后延迟消失 */
.menu-item {
    transition: background-color 0.3s ease;
}

/* 子菜单在鼠标移开后延迟消失 */
.menu-item:hover .submenu {
    transition: opacity 0.3s ease, visibility 0.3s ease;
}

.menu-item .submenu {
    transition-delay: 1.5s; /* 添加延迟消失效果 */
}

/* 阻止点击行为,确保只是预览 */
.menu-preview a {
    pointer-events: none;
    color: #333;
    text-decoration: none;
    cursor: default;
}

  

menu.js

document.addEventListener('DOMContentLoaded', function() {
    
    // 禁用菜单预览的点击事件
    const previewLinks = document.querySelectorAll('.menu-preview .menu-item');
    previewLinks.forEach(function(link) {
        link.addEventListener('click', function(event) {
            event.preventDefault();  // 禁用默认的点击行为
        });
    });

    // 处理菜单悬停显示子菜单
    const menuItems = document.querySelectorAll('.menu-item');
    
    menuItems.forEach(function(menuItem) {
        let timer; // 定义延时计时器

        menuItem.addEventListener('mouseenter', function() {
            clearTimeout(timer); // 清除离开时的计时器,确保子菜单正常显示
            const submenu = this.querySelector('.submenu');
            if (submenu) {
                submenu.style.display = 'block';
                submenu.style.opacity = '1';
                submenu.style.visibility = 'visible';
            }
        });

        menuItem.addEventListener('mouseleave', function() {
            const submenu = this.querySelector('.submenu');
            if (submenu) {
                timer = setTimeout(function() {
                    submenu.style.opacity = '0';
                    submenu.style.visibility = 'hidden';
                }, 1500); // 鼠标离开 1.5 秒后隐藏子菜单
            }
        });
    });
    
    // 全选功能
    const selectAllCheckbox = document.getElementById('select-all');
    if (selectAllCheckbox) {
        selectAllCheckbox.addEventListener('click', function () {
            const checkboxes = document.querySelectorAll('input[name="cmo_selected_categories[]"]');
            checkboxes.forEach(checkbox => checkbox.checked = this.checked);
            console.log('全选按钮已点击');
        });
    }

    // 按钮点击事件
    const addToMenuButton = document.getElementById('cmo_add_to_menu');
    if (addToMenuButton) {
        addToMenuButton.addEventListener('click', function (event) {
            console.log('添加分类到选定菜单按钮已点击');
            handleMenuAction('cmo_add_to_menu', '添加分类到选定菜单', event);
        });
    }

    const backupMenuButton = document.getElementById('cmo_backup_menu');
    if (backupMenuButton) {
        backupMenuButton.addEventListener('click', function (event) {
            handleMenuAction('cmo_backup_menu', '备份当前菜单', event);
        });
    }

    const restoreMenuButton = document.getElementById('cmo_restore_menu');
    if (restoreMenuButton) {
        restoreMenuButton.addEventListener('click', function (event) {
            handleMenuAction('cmo_restore_menu', '恢复备份菜单', event);
        });
    }

    // 预览菜单
    const menuSelector = document.getElementById('cmo_menu_selector');
    if (menuSelector) {
        menuSelector.addEventListener('change', function () {
            const menuId = this.value;
            loadMenuPreview(menuId);
        });
    }
});

// 处理按钮点击的AJAX请求
function handleMenuAction(action, message, event) {
    const menuId = document.getElementById('cmo_menu_selector').value;
    console.log('处理菜单:', menuId);
    const button = event.target;
    button.disabled = true;
    button.innerHTML = '处理中...';

    // 获取选中的分类
    const selectedCategories = Array.from(document.querySelectorAll('input[name="cmo_selected_categories[]"]:checked')).map(input => input.value);

    if (selectedCategories.length === 0) {
        alert("未选择任何分类");
        button.disabled = false;
        button.innerHTML = message;
        console.log('未选择分类');
        return;
    }

    console.log('发送的分类:', selectedCategories);

    // 发送 AJAX 请求
    jQuery.post(ajaxurl, {
        action: action,
        menu_id: menuId,
        selected_categories: selectedCategories  // 传递选中的分类数据
    }, function(response) {
        console.log('Response:', response);
        button.disabled = false;
        button.innerHTML = message;

        if (response.success) {
            alert(response.data);
            console.log('操作成功');
            if (action === 'cmo_add_to_menu' || action === 'cmo_preview_menu') {
                loadMenuPreview(menuId);
            }
        } else {
            console.log('操作失败:', response.data);
            alert('操作失败: ' + response.data);
        }
    });
}

// 加载菜单预览
function loadMenuPreview(menuId) {
    document.getElementById('preview-content').innerHTML = '加载中...';
    jQuery.post(ajaxurl, {
        action: 'cmo_preview_menu',
        menu_id: menuId
    }, function (response) {
        if (response.success) {
            document.getElementById('preview-content').innerHTML = response.data;
        } else {
            document.getElementById('preview-content').innerHTML = '预览加载失败';
        }
    });
}

  

 

标签:cmo,插件,菜单,menu,item,WordPress,items,排序,id
From: https://www.cnblogs.com/Boboschen/p/18439607

相关文章

  • Java 冒泡排序 (Bubble Sort) ✨ 代码版 + Emoji讲解
    冒泡排序的基本思想就是让“大泡泡”不断往上浮,直到整个数组像泡泡浴一样排序好!......
  • uniapp [安卓苹果App端] - 详细实现手机蓝牙连接打印机及打印票据小票/标签/面单/热敏
    前言网上的教程乱七八糟,文本提供优质示例代码。在uni-appApp端(安卓APP|苹果APP)开发中,详解实现“手机蓝牙连接并使用蓝牙打印机”,uniAppApp端手机使用蓝牙连接打印机进行打印的相关功能,uniapp苹果安卓app实现开启蓝牙并搜索附近范围的蓝牙打印机对接全流程,支持打印......
  • 希尔排序(缩小增量排序)
    点击查看代码packageSort;importjava.util.*;publicclass希尔排序增量{publicstaticvoidmain(String[]args){//三个循环控制intarray[]={2,9,8,6,10,12,7};intn=array.length;intinc;//增量intkey;//中......
  • Deepseek AI 与插件Continue代码智能助手
       Deepseek的代码AI能力智能助手在代码生成与补全、代码修复与优化、智能问答。似乎是替代CursorAI的方案,以下介绍是VSCODE中安装插件Continue准备工作DeepseekAPIaccessKey申请配置config.json配置如下{"completionOptions":{"BaseCompletionOptions":{"tempe......
  • 信息学奥赛复赛复习06-CSP-J2020-02直播获奖-向上取整、向下取整、整数除法、最大值、
    PDF文档公众号回复关键字:2024092812020CSP-J题目1优秀的拆分[题目描述]NOI2130即将举行。为了增加观赏性,CCF决定逐一评出每个选手的成绩,并直播即时的获奖分数线。本次竞赛的获奖率为w%,即当前排名前w%的选手的最低成绩就是即时的分数线更具体地,若当前已评出了p个......
  • nexus 美化桌面插件安装使用
    请看下面效果图,就是精美的桌面插件软件下载链接:https://pan.baidu.com/s/11jKd7hSYFquR6eiU-8Y6dw 提取码:ehye下载完会得到一个文件夹,打开文件夹会看到nexus.zip压缩包打开,然后点击NexusSetup.exe进行安装,一路默认就可以。安装好之后点击运行Nexus。这时候你就会发现桌......
  • Stable Diffusion绘画 | AnimateDiff:用AI制作动画(附插件安装包)
    使用AnimateDiff插件,我们只需要按时间节点,输入不同的提示词,就可以非常轻松地生成一系列丝滑的动画。AnimateDiff的底层技术框架,是由上海人工智能实验室&香港中文大学&斯坦福大学联合研发的,它能很好地结合SD的各种模型,以及配合ControlNet和Upscale来生成出......
  • 一些超好用的 GitHub 插件和技巧
    聊聊我平时使用GitHub时学到的一些插件、技巧。‍‍浏览器插件在我的另一篇博客浏览器插件推荐里提到过跟GitHub相关的一些插件,这里重复下:Sourcegraph:在线打开项目,方便阅读,将GitHub变得和IDE一般,集成各种功能,参考爱了爱了,这个GitHub的Chrome神仙插件把我整的......
  • 双端之Nginx+Php结合PostgreSQL搭建Wordpress
    第一台虚拟机:安装Nginx更新系统包列表:sudoaptupdate安装Nginx及php扩展:sudoaptinstallnginxphp-fpmphp-pgsqlphp-mysqli-y启动Nginx服务:sudosystemctlstartnginx检查Nginx是否正常运行:xdg-openhttp://localhost注意:终端命令打开网址打......
  • LAMP+WordPress 部署与配置
    LAMP+WordPress部署与配置安装Apachesudodnfinstallhttpd启动Apache服务sudosystemctlenablehttpdsudosystemctlstarthttpd开放端口sudofirewall-cmd--permanent--add-service=httpsudofirewall-cmd--permanent--add-service=httpssudofirewall-cm......