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.

472 lines
18 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<?php
/**
* 主题核心文件
* 负责加载各个功能模块
*/
// 防止直接访问
if (!defined('ABSPATH')) {
exit;
}
// 导入错误处理配置(优先加载)
require_once 'inc/error-handler.php';
// 导入主题初始化配置
require_once 'inc/init-config.php';
// 导入主题基础设置
require_once 'inc/theme-setup.php';
// 导入后台管理配置
require_once 'inc/admin-config.php';
// 导入资源加载配置
require_once 'inc/assets-loader.php';
// 导入媒体配置
require_once 'inc/media-config.php';
// 导入清理和优化功能
require_once 'inc/cleanup.php';
// 导入性能优化配置文件
require_once 'inc/performance-config.php';
// 导入自定义器配置
require_once 'inc/customizer.php';
// 导入短代码功能
require_once 'inc/shortcode.php';
// 导入SEO配置功能
require_once 'inc/seo-config.php';
// 导入自定义代码管理功能
require_once 'inc/custom-code-config.php';
// 导入Header/Footer自定义代码功能暂时注释掉以避免冲突
// require_once 'inc/custom-code.php';
// 导入SMTP邮件配置
require_once 'inc/smtp/smtp-config.php';
require_once 'inc/smtp/smtp-admin.php';
// 导入维护模式功能
require_once 'inc/maintenance-mode.php';
// 导入Cookie Consent功能
require_once 'inc/cookie-consent.php';
// 导入FAQ自定义文章类型
require_once 'inc/cpt-faq.php';
// 导入文章浏览量统计功能
require_once 'inc/post-views.php';
// 导入调试工具(仅在调试模式下)
// if (defined('WP_DEBUG') && WP_DEBUG) {
// require_once 'test-menu-debug.php';
// }
/**
* 增强编辑角色权限
* 为编辑角色添加外观管理的全部功能
*/
function enhance_editor_capabilities() {
// 获取编辑角色对象
$role = get_role('editor');
if ($role) {
// 添加外观相关的权限
$role->add_cap('edit_theme_options'); // 编辑主题选项
$role->add_cap('customize'); // 自定义器
$role->add_cap('switch_themes'); // 切换主题
$role->add_cap('edit_themes'); // 编辑主题
$role->add_cap('update_themes'); // 更新主题
$role->add_cap('install_themes'); // 安装主题
$role->add_cap('delete_themes'); // 删除主题
$role->add_cap('upload_themes'); // 上传主题
}
}
// 在主题激活时运行一次
add_action('after_switch_theme', 'enhance_editor_capabilities');
// 确保在插件加载后运行一次
add_action('init', 'enhance_editor_capabilities');
// 在导航菜单管理页面显示菜单ID
function nenghui_show_menu_id_in_nav_menus() {
// 只在nav-menus.php页面加载
global $pagenow;
if ($pagenow !== 'nav-menus.php') {
return;
}
// 获取所有菜单
$menus = wp_get_nav_menus();
if (empty($menus)) {
return;
}
?>
<style>
.nenghui-menu-id-info {
background: #f1f1f1;
border: 1px solid #ccc;
border-radius: 4px;
padding: 10px;
margin: 10px 0;
font-size: 13px;
}
.nenghui-menu-id-info h4 {
margin: 0 0 8px 0;
color: #23282d;
}
.nenghui-menu-list {
margin: 0;
padding: 0;
list-style: none;
}
.nenghui-menu-list li {
margin: 4px 0;
padding: 4px 8px;
background: #fff;
border-radius: 2px;
display: flex;
justify-content: space-between;
align-items: center;
}
.nenghui-menu-name {
font-weight: 500;
}
.nenghui-menu-id {
color: #666;
font-family: monospace;
background: #f9f9f9;
padding: 2px 6px;
border-radius: 2px;
font-size: 12px;
}
</style>
<script>
jQuery(document).ready(function($) {
// 在页面顶部添加菜单ID信息
var menuInfo = '<div class="nenghui-menu-id-info">' +
'<h4>📋 可用菜单及其ID</h4>' +
'<ul class="nenghui-menu-list">';
<?php foreach ($menus as $menu): ?>
menuInfo += '<li>' +
'<span class="nenghui-menu-name"><?php echo esc_js($menu->name); ?></span>' +
'<span class="nenghui-menu-id">ID: <?php echo esc_js($menu->term_id); ?></span>' +
'</li>';
<?php endforeach; ?>
menuInfo += '</ul>' +
'<p style="margin: 8px 0 0 0; color: #666; font-size: 12px;">' +
'💡 提示:在短代码中使用 <code>[nenghui_about_nav menu_id="菜单ID"]</code> 来指定菜单' +
'</p></div>';
// 将信息插入到页面顶部
$('#nav-menus-frame').prepend(menuInfo);
// 为现有的菜单标题添加ID显示
$('.menu-edit').each(function() {
var $menuEdit = $(this);
var menuId = $menuEdit.find('input[name="menu"]').val();
if (menuId) {
var $title = $menuEdit.find('.menu-name-label');
if ($title.length > 0) {
var currentText = $title.text();
if (currentText && !currentText.includes('(ID:')) {
$title.text(currentText + ' (ID: ' + menuId + ')');
}
}
}
});
// 为主题位置的下拉菜单添加ID显示
$('.menu-theme-locations select option').each(function() {
var $option = $(this);
var optionValue = $option.val();
var optionText = $option.text();
if (optionValue && optionText && !optionText.includes('(ID:')) {
$option.text(optionText + ' (ID: ' + optionValue + ')');
}
});
});
</script>
<?php
}
add_action('admin_footer-nav-menus.php', 'nenghui_show_menu_id_in_nav_menus');
// 在菜单管理页面添加帮助信息
function nenghui_add_menu_help_info() {
$screen = get_current_screen();
if ($screen && $screen->id === 'nav-menus') {
$screen->add_help_tab(array(
'id' => 'nenghui-menu-ids',
'title' => '菜单ID使用',
'content' => '<h3>如何使用菜单ID</h3>' .
'<p>每个菜单都有一个唯一的数字ID您可以在短代码中使用这些ID来指定特定的菜单。</p>' .
'<h4>About导航短代码示例</h4>' .
'<ul>' .
'<li><code>[nenghui_about_nav]</code> - 使用自定义器中设置的默认菜单</li>' .
'<li><code>[nenghui_about_nav menu_id="2"]</code> - 使用ID为2的菜单</li>' .
'<li><code>[nenghui_about_nav menu_id="5"]</code> - 使用ID为5的菜单</li>' .
'</ul>' .
'<p><strong>注意:</strong>菜单ID在页面顶部的信息框中显示请使用正确的ID。</p>'
));
}
}
add_action('current_screen', 'nenghui_add_menu_help_info');
// 导入主题配置文件
// require_once 'theme-options.php'; // 暂时注释掉,文件不存在
// 导入小工具配置
require_once 'widgets/widgets-config.php';
// 刷新重写规则以确保FAQ归档页面正常工作
function nenghui_flush_rewrite_rules() {
// 只在主题激活时执行一次
if (get_option('nenghui_rewrite_rules_flushed') !== '1') {
flush_rewrite_rules();
update_option('nenghui_rewrite_rules_flushed', '1');
}
}
add_action('after_switch_theme', 'nenghui_flush_rewrite_rules');
// 当FAQ文章类型注册后刷新重写规则
function nenghui_flush_rewrite_rules_on_init() {
static $flushed = false;
if (!$flushed && get_option('nenghui_faq_rewrite_flushed') !== '1') {
flush_rewrite_rules();
update_option('nenghui_faq_rewrite_flushed', '1');
$flushed = true;
}
}
add_action('init', 'nenghui_flush_rewrite_rules_on_init', 999);
// 所有功能已拆分到独立的配置文件中:
// - 主题设置: inc/theme-setup.php
// - 后台管理: inc/admin-config.php
// - 资源加载: inc/assets-loader.php
// - 媒体配置: inc/media-config.php
// - 初始化配置: inc/init-config.php
// - 清理优化: inc/cleanup.php
// - 性能配置: inc/performance-config.php
// - 自定义器: inc/customizer.php
// - 短代码: inc/shortcode.php
/**
* 自定义导航菜单Walker类支持多级下拉菜单
*/
class Nenghui_Walker_Nav_Menu extends Walker_Nav_Menu {
// 开始输出子菜单
function start_lvl(&$output, $depth = 0, $args = null) {
$indent = str_repeat("\t", $depth);
$output .= "\n$indent<ul class=\"sub-menu\">\n";
}
// 结束输出子菜单
function end_lvl(&$output, $depth = 0, $args = null) {
$indent = str_repeat("\t", $depth);
$output .= "$indent</ul>\n";
}
// 显示元素
function display_element($element, &$children_elements, $max_depth, $depth = 0, $args, &$output) {
$id_field = $this->db_fields['id'];
if (is_object($args[0])) {
$args[0]->has_children = !empty($children_elements[$element->$id_field]);
}
return parent::display_element($element, $children_elements, $max_depth, $depth, $args, $output);
}
// 开始输出菜单项
function start_el(&$output, $item, $depth = 0, $args = null, $id = 0) {
$indent = ($depth) ? str_repeat("\t", $depth) : '';
$classes = empty($item->classes) ? array() : (array) $item->classes;
$classes[] = 'menu-item-' . $item->ID;
// 检查是否有子菜单
$has_children = !empty($args->has_children);
if ($has_children) {
$classes[] = 'menu-item-has-children';
}
$class_names = join(' ', apply_filters('nav_menu_css_class', array_filter($classes), $item, $args));
$class_names = $class_names ? ' class="' . esc_attr($class_names) . '"' : '';
$id = apply_filters('nav_menu_item_id', 'menu-item-'. $item->ID, $item, $args);
$id = $id ? ' id="' . esc_attr($id) . '"' : '';
$output .= $indent . '<li' . $id . $class_names .'>';
$attributes = ! empty($item->attr_title) ? ' title="' . esc_attr($item->attr_title) .'"' : '';
$attributes .= ! empty($item->target) ? ' target="' . esc_attr($item->target ) .'"' : '';
$attributes .= ! empty($item->xfn) ? ' rel="' . esc_attr($item->xfn ) .'"' : '';
$attributes .= ! empty($item->url) ? ' href="' . esc_attr($item->url ) .'"' : '';
$item_output = isset($args->before) ? $args->before : '';
$item_output .= '<a' . $attributes . '>';
$item_output .= (isset($args->link_before) ? $args->link_before : '') . apply_filters('the_title', $item->title, $item->ID) . (isset($args->link_after) ? $args->link_after : '');
// 如果有子菜单,添加下拉箭头
if ($has_children) {
$item_output .= ' <span class="dropdown-arrow">▼</span>';
}
$item_output .= '</a>';
$item_output .= isset($args->after) ? $args->after : '';
$output .= apply_filters('walker_nav_menu_start_el', $item_output, $item, $depth, $args);
}
// 结束输出菜单项
function end_el(&$output, $item, $depth = 0, $args = null) {
$output .= "</li>\n";
}
}
function get_post_meta_by_key($key, $cate_type) {
global $wpdb;
$table = $wpdb->postmeta;
$result = $wpdb->get_var($wpdb->prepare(
"SELECT meta_value FROM $table WHERE meta_key = %s AND post_id IN (
SELECT post_id FROM $table WHERE meta_key = 'cate_type' AND meta_value LIKE %s
) LIMIT 1",
$key,
'%' . $wpdb->esc_like($cate_type) . '%'
));
return $result;
}
add_action('wp_ajax_load_more_products', 'load_more_products_callback');
add_action('wp_ajax_nopriv_load_more_products', 'load_more_products_callback');
function load_more_products_callback() {
check_ajax_referer('load_more_products_nonce', 'nonce');
$offset = intval($_POST['offset']);
$per_page = intval($_POST['per_page']);
$category = isset($_POST['category']) ? sanitize_text_field($_POST['category']) : '';
$meta_query = array();
if (!empty($category) && $category !== 'all') {
$meta_query[] = array(
'key' => 'cate_type',
'value' => $category,
'compare' => 'LIKE'
);
}
$query_args = array(
'post_type' => 'products',
'posts_per_page' => $per_page,
'offset' => $offset,
'meta_query' => $meta_query,
'post_status' => 'publish'
);
$products_query = new WP_Query($query_args);
$products = array();
if ($products_query->have_posts()) {
while ($products_query->have_posts()) {
$products_query->the_post();
$post_id = get_the_ID();
$cate_type = get_post_meta($post_id, 'cate_type', true);
$cover_image = get_the_post_thumbnail_url($post_id, 'product-cover-medium');
if (empty($cover_image)) {
$cover_image = get_post_meta($post_id, '_product_banner_url', true);
}
if (empty($cover_image)) {
$cover_image = get_template_directory_uri() . '/assets/images/products-1.webp';
}
$usage_scenario_data = get_post_meta($post_id, '_usage_scenario_data', true);
$description = '';
if (!empty($usage_scenario_data) && isset($usage_scenario_data['bottom_text'])) {
$description = $usage_scenario_data['bottom_text'];
}
$attr_keys = get_post_meta($post_id, 'attr_key', true);
$attr_values = get_post_meta($post_id, 'attr_value', true);
$attr_keys_array = !empty($attr_keys) ? explode(',', $attr_keys) : array();
$attr_values_array = !empty($attr_values) ? explode(',', $attr_values) : array();
$attrs = array();
for ($i = 0; $i < min(4, count($attr_keys_array)); $i++) {
if (isset($attr_keys_array[$i]) && isset($attr_values_array[$i])) {
$attrs[] = array(
'key' => trim($attr_keys_array[$i]),
'value' => trim($attr_values_array[$i])
);
}
}
$efficiency = get_post_meta($post_id, 'efficiency', true);
$is_new = get_post_meta($post_id, 'is_new', true);
$is_new_value = filter_var($is_new, FILTER_VALIDATE_BOOLEAN);
ob_start();
?>
<div data-category="<?php echo esc_attr($cate_type); ?>" class="product-card break-inside-avoid bg-white dark:bg-card-dark rounded-xl overflow-hidden border border-[#e5e7eb] dark:border-[#2a3441] shadow-sm hover:shadow-card-hover hover:border-primary/40 group" data-aos="fade-up" data-aos-delay="0">
<div class="skeleton-wrapper relative h-64 w-full bg-gradient-to-b from-[#787878] to-white dark:from-[#333] dark:to-[#111318] flex items-center justify-center p-6 transition-all duration-500 group-hover:from-[#666666] group-hover:to-[#e6fcf5]">
<?php if (!empty($is_new)): ?>
<div class="absolute top-4 left-4 bg-primary text-white text-xs font-bold px-2.5 py-1 rounded shadow-sm z-10">
NEW
</div>
<?php endif; ?>
<?php if (!empty($efficiency)): ?>
<div class="absolute top-4 right-4 bg-white/90 dark:bg-[#2a3441]/90 backdrop-blur text-primary text-xs font-bold px-2.5 py-1 rounded shadow-sm border border-primary/10 z-10">
<?php echo esc_html($efficiency); ?>
</div>
<?php endif; ?>
<div class="lazy-target w-full h-full bg-center bg-no-repeat bg-contain transform group-hover:scale-105 transition-transform duration-500" data-alt="<?php echo esc_attr(get_the_title()); ?>" data-bg="<?php echo esc_url($cover_image); ?>" style="background-image: url('<?php echo esc_url($cover_image); ?>');"></div>
</div>
<div class="p-5">
<div class="flex justify-between items-start mb-2">
<div class="flex items-center gap-2">
<h3 class="text-xl font-bold font-display text-[#111318] dark:text-white group-hover:text-primary transition-colors"><?php echo esc_html(get_the_title()); ?></h3>
<?php if ($is_new_value): ?>
<span class="bg-primary/10 text-primary text-[10px] font-bold px-2 py-0.5 rounded-full border border-primary/20 animate-pulse">NEW</span>
<?php endif; ?>
</div>
</div>
<div class="grid grid-cols-2 gap-y-3 gap-x-4 mb-5 text-sm">
<?php foreach ($attrs as $attr): ?>
<div class="bg-gray-50 dark:bg-[#1f2937] p-2 rounded <?php echo $is_new_value ? 'border-l-2 border-primary' : ''; ?>">
<p class="text-[#5f6e8c] dark:text-gray-500 text-[10px] uppercase tracking-wider"><?php echo esc_html($attr['key']); ?></p>
<p class="font-semibold dark:text-gray-200"><?php echo esc_html($attr['value']); ?></p>
</div>
<?php endforeach; ?>
</div>
<p class="text-[#5f6e8c] dark:text-gray-400 text-sm leading-relaxed mb-6 line-clamp-4">
<?php echo wp_kses_post($description); ?>
</p>
<a href="<?php echo esc_url(get_permalink()); ?>" class="product-detail-link">
<button class="w-full flex items-center justify-center gap-2 h-11 rounded-lg bg-[#f0f1f5] dark:bg-[#2a3441] text-[#111318] dark:text-white text-sm font-bold hover:bg-[#e0e2e8] dark:hover:bg-[#374151] transition-all group-hover:bg-primary group-hover:text-white group-hover:shadow-glow">
<span>View Datasheet</span>
<span class="material-symbols-outlined text-[18px] group-hover:translate-x-1 transition-transform">&#xe5c8;</span>
</button>
</a>
</div>
</div>
<?php
$products[] = array(
'html' => ob_get_clean()
);
}
wp_reset_postdata();
}
wp_send_json_success(array('products' => $products));
}
?>