[add]添加从数据库获取产品列表信息

dev
huyuanxiang 6 days ago
parent 5519bdf676
commit 6a461052f9

1
.gitignore vendored

@ -5,6 +5,7 @@ bin-release/
[Bb]in/ [Bb]in/
wp-admin/ wp-admin/
wp-includes/ wp-includes/
html-temp/
wp-content/languages/ wp-content/languages/
wp-content/mu-plugins/ wp-content/mu-plugins/
wp-content/plugins/ wp-content/plugins/

@ -0,0 +1,611 @@
# Nenghui Energy Theme - 短代码使用文档
本文档提供了 Nenghui Energy 主题中所有可用短代码的详细说明和使用示例。
## 目录
1. [产品相关短代码](#产品相关短代码)
2. [新闻相关短代码](#新闻相关短代码)
3. [关于页面短代码](#关于页面短代码)
4. [联系页面短代码](#联系页面短代码)
5. [通用组件短代码](#通用组件短代码)
6. [EPC相关短代码](#epc相关短代码)
---
## 产品相关短代码
### `nenghui_products_list` - 产品列表
显示产品列表,支持分类筛选和分页。
**基本用法:**
```php
[nenghui_products_list]
```
**完整参数:**
```php
[nenghui_products_list
per_page="6"
category="residential"
order="date"
orderby="DESC"
category_order=""]
```
**参数说明:**
- `per_page` - 每页显示的产品数量默认6
- `category` - 筛选特定分类(留空显示所有)
- `order` - 排序方式默认date
- `orderby` - 排序字段默认DESC
- `category_order` - 自定义分类排序
**产品自定义字段:**
- `cate_type` - 产品分类(必需)
- `cate_type_value` - 分类显示名称
- `efficiency` - 效率值≥93% Efficiency
- `is_new` - 是否为新产品true/false
- `attr_key` - 属性名称(逗号分隔)
- `attr_value` - 属性值(逗号分隔)
- `_product_banner_url` - 产品横幅图片URL
- `_usage_scenario_data` - 使用场景数据包含bottom_text
**示例:**
```php
// 显示所有产品每页9个
[nenghui_products_list per_page="9"]
// 只显示residential分类的产品
[nenghui_products_list category="residential"]
// 自定义排序
[nenghui_products_list order="title" orderby="ASC"]
```
---
### `nenghui_products_banner` - 产品横幅
显示产品页面横幅。
**基本用法:**
```php
[nenghui_products_banner]
```
或简化版本:
```php
[products_banner]
```
---
### `nenghui_warehousing_distribution` - 仓储配送
显示仓储配送信息。
**基本用法:**
```php
[nenghui_warehousing_distribution]
```
或简化版本:
```php
[warehousing_distribution]
```
---
## 新闻相关短代码
### `nenghui_news` - 新闻列表
显示新闻文章列表。
**基本用法:**
```php
[nenghui_news]
```
**完整参数:**
```php
[nenghui_news
title="最新资讯"
category_id="1"
posts_count="6"
order_by="date"
order="DESC"]
```
**参数说明:**
- `title` - 模块标题
- `category_id` - 分类ID
- `posts_count` - 显示文章数量
- `order_by` - 排序字段
- `order` - 排序方向
---
### `nenghui_news_grid` - 新闻网格
以网格布局显示新闻。
**基本用法:**
```php
[nenghui_news_grid]
```
---
## 关于页面短代码
### `nenghui_about_nav` - 关于导航
显示关于页面的导航菜单。
**基本用法:**
```php
[nenghui_about_nav]
```
**自定义参数:**
```php
[nenghui_about_nav menu_id="123"]
```
**参数说明:**
- `menu_id` - 指定菜单ID留空使用自定义器设置的默认菜单
---
### `nenghui_about_company` - 关于公司
显示公司介绍信息。
**基本用法:**
```php
[nenghui_about_company]
```
**自定义参数:**
```php
[nenghui_about_company show_animation="true"]
```
**参数说明:**
- `show_animation` - 是否显示动画效果
---
### `nenghui_development_history` - 发展历程
显示公司发展历程时间线。
**基本用法:**
```php
[nenghui_development_history]
```
**自定义参数:**
```php
[nenghui_development_history show_animation="true"]
```
---
### `nenghui_certification_gallery` - 认证画廊
显示公司认证证书画廊。
**基本用法:**
```php
[nenghui_certification_gallery]
```
**自定义参数:**
```php
[nenghui_certification_gallery
columns="5"
lightbox="true"
animation="true"]
```
**参数说明:**
- `columns` - 每行显示列数1-6
- `lightbox` - 是否启用灯箱效果
- `animation` - 是否启用动画效果
---
### `nenghui_technical_service` - 技术服务
显示技术服务信息。
**基本用法:**
```php
[nenghui_technical_service]
```
**自定义参数:**
```php
[nenghui_technical_service
title="可靠的技术服务"
subtitle="提升客户体验"]
```
---
### `black_about_company_banner` - 关于公司横幅
显示关于页面的横幅。
**基本用法:**
```php
[black_about_company_banner]
```
---
### `nenghui_black_about_info` - 关于信息
显示公司详细信息。
**基本用法:**
```php
[nenghui_black_about_info]
```
或简化版本:
```php
[black_about_info]
```
---
### `business_process` - 业务流程
显示业务流程图。
**基本用法:**
```php
[business_process]
```
---
## 联系页面短代码
### `nenghui_contact_form` - 联系表单
显示联系表单。
**基本用法:**
```php
[nenghui_contact_form]
```
**自定义参数:**
```php
[nenghui_contact_form form_id="1" show_animation="true"]
```
**参数说明:**
- `form_id` - 表单ID
- `show_animation` - 是否显示动画效果
---
### `nenghui_contact_map` - 联系地图
显示联系地图。
**基本用法:**
```php
[nenghui_contact_map]
```
---
### `nenghui_overseas_services` - 海外服务
显示海外服务信息。
**基本用法:**
```php
[nenghui_overseas_services]
```
---
## 通用组件短代码
### `nenghui_banner` - 轮播横幅
显示轮播横幅。
**基本用法:**
```php
[nenghui_banner]
```
**自定义参数:**
```php
[nenghui_banner autoplay="true"]
```
**参数说明:**
- `autoplay` - 是否自动播放
---
### `nenghui_futures` - 未来展望
显示未来展望内容。
**基本用法:**
```php
[nenghui_futures]
```
**自定义参数:**
```php
[nenghui_futures title="未来展望" show_animation="true"]
```
---
### `nenghui_tabs` - 选项卡
显示选项卡内容。
**基本用法:**
```php
[nenghui_tabs]
```
**自定义参数:**
```php
[nenghui_tabs tabs_count="3" show_animation="true"]
```
---
### `nenghui_flowchart_tabs` - 流程图选项卡
显示流程图选项卡。
**基本用法:**
```php
[nenghui_flowchart_tabs]
```
---
### `nenghui_banner_title` - 标题横幅
显示带标题的横幅。
**基本用法:**
```php
[nenghui_banner_title title="关于我们" description="我们致力于提供最优质的服务"]
```
**完整参数:**
```php
[nenghui_banner_title
title="关于我们"
description="我们致力于提供最优质的服务"
bg_image="https://example.com/image.jpg"
height="70vh"
overlay_opacity="0.6"
show_animation="true"]
```
**参数说明:**
- `title` - 标题
- `description` - 描述
- `bg_image` - 背景图片URL
- `height` - 高度支持px、vh、%
- `overlay_opacity` - 遮罩透明度0-1
- `show_animation` - 是否显示动画
---
### `black_maps` - 黑色地图
显示交互式地图。
**基本用法:**
```php
[black_maps]
```
**自定义参数:**
```php
[black_maps height="100vh" show_loading="true"]
```
**参数说明:**
- `height` - 地图高度
- `show_loading` - 是否显示加载动画
---
### `nenghui_video` - 视频
显示视频播放器。
**基本用法:**
```php
[nenghui_video video_url="https://example.com/video.mp4"]
```
**完整参数:**
```php
[nenghui_video
video_url="https://example.com/video.mp4"
cover_image="https://example.com/cover.jpg"
title="我们的企业视频"
description="了解我们的产品和服务"
play_button_text="立即播放"
show_overlay="true"
overlay_opacity="0.5"
height="80vh"
autoplay="false"
muted="true"
controls="true"]
```
**参数说明:**
- `video_url` - 视频URL必需
- `cover_image` - 封面图片URL
- `title` - 视频标题
- `description` - 视频描述
- `play_button_text` - 播放按钮文字
- `show_overlay` - 是否显示遮罩
- `overlay_opacity` - 遮罩透明度
- `height` - 视频高度
- `autoplay` - 是否自动播放
- `muted` - 是否静音
- `controls` - 是否显示控制栏
---
### `nenghui_download_center` - 下载中心
显示下载中心。
**基本用法:**
```php
[nenghui_download_center]
```
---
### `nenghui_faq` - 常见问题
显示常见问题列表。
**基本用法:**
```php
[nenghui_faq]
```
---
### `nenghui_cases` - 案例展示
显示案例展示。
**基本用法:**
```php
[nenghui_cases]
```
---
## EPC相关短代码
### `nenghui_epc` - EPC解决方案
显示EPC解决方案。
**基本用法:**
```php
[nenghui_epc]
```
**自定义参数:**
```php
[nenghui_epc
title="EPC Solutions"
subtitle="Beyond Hardware: Total EPC Solutions from NengHui Design Institute"
bg_image="https://example.com/epc-bg.jpg"]
```
---
### `nenghui_epc_banner` - EPC横幅
显示EPC横幅。
**基本用法:**
```php
[nenghui_epc_banner]
```
---
## 使用技巧
### 1. 在页面编辑器中使用
在WordPress页面编辑器中直接输入短代码即可
```
[nenghui_products_list per_page="9"]
```
### 2. 在模板文件中使用
在主题模板文件中使用 `do_shortcode()` 函数:
```php
<?php echo do_shortcode('[nenghui_products_list per_page="9"]'); ?>
```
### 3. 组合使用多个短代码
可以在同一个页面中使用多个短代码:
```
[nenghui_banner_title title="我们的产品"]
[nenghui_products_list per_page="9"]
[nenghui_contact_form]
```
### 4. 响应式设计
所有短代码都支持响应式设计,会自动适应不同屏幕尺寸。
### 5. 深色模式
所有短代码都支持深色模式,会自动根据系统设置切换主题。
## 常见问题
### Q: 短代码不显示怎么办?
A: 请确保:
1. 短代码名称拼写正确
2. 主题已正确激活
3. 没有PHP错误检查调试日志
### Q: 如何自定义短代码样式?
A: 可以通过以下方式自定义:
1. 在自定义器中修改相关设置
2. 使用CSS覆盖默认样式
3. 修改对应的模板文件
### Q: 短代码参数不生效怎么办?
A: 请确保:
1. 参数名称拼写正确
2. 参数值格式正确
3. 没有特殊字符冲突
### Q: 如何添加新的短代码?
A: 可以在 `inc/shortcode.php` 文件中添加新的短代码函数,参考现有短代码的实现方式。
## 技术支持
如需技术支持,请联系开发团队或查看主题文档。
---
**文档版本:** 1.0
**最后更新:** 2026-02-09
**主题版本:** nenghui-energy-theme-4

@ -334,4 +334,139 @@ class Nenghui_Walker_Nav_Menu extends Walker_Nav_Menu {
} }
} }
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));
}
?> ?>

@ -1693,4 +1693,30 @@ function nenghui_business_process_shortcode($atts) {
return $output; return $output;
} }
add_shortcode('business_process', 'nenghui_business_process_shortcode'); add_shortcode('business_process', 'nenghui_business_process_shortcode');
function nenghui_products_list_shortcode($atts) {
if (!is_array($atts)) {
$atts = array();
}
$atts = shortcode_atts(array(
'id' => 'nenghui-products-list-shortcode',
'class' => '',
'per_page' => '3',
'category' => '',
'order' => 'date',
'orderby' => 'DESC',
'category_order' => ''
), $atts);
ob_start();
global $products_list_shortcode_atts;
$products_list_shortcode_atts = $atts;
include get_template_directory() . '/template-parts/blocks/block-products-list.php';
return ob_get_clean();
}
add_shortcode('nenghui_products_list', 'nenghui_products_list_shortcode');

@ -226,8 +226,7 @@
.menu-items li.menu-item-has-children > a .dropdown-arrow { .menu-items li.menu-item-has-children > a .dropdown-arrow {
font-size: 0.7rem; font-size: 0.7rem;
margin-left: 8px; padding: 10px 0 10px 10px;
padding: 10px 0 10px 20px;
transition: transform 0.3s ease; transition: transform 0.3s ease;
display: inline-block; display: inline-block;
color: inherit; color: inherit;

@ -0,0 +1,889 @@
<?php
if (!defined('ABSPATH')) {
exit;
}
global $products_list_shortcode_atts;
$atts = $products_list_shortcode_atts;
$per_page = intval($atts['per_page']);
$category = sanitize_text_field($atts['category']);
$order = sanitize_text_field($atts['order']);
$orderby = sanitize_text_field($atts['orderby']);
$category_order = sanitize_text_field($atts['category_order']);
$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,
'paged' => get_query_var('paged') ? get_query_var('paged') : 1,
'meta_query' => $meta_query,
'order' => $order,
'orderby' => $orderby,
'post_status' => 'publish'
);
$products_query = new WP_Query($query_args);
$all_products_args = array(
'post_type' => 'products',
'posts_per_page' => -1,
'post_status' => 'publish'
);
$all_products = get_posts($all_products_args);
$unique_cate_types = array();
foreach ($all_products as $product) {
$cate_type = get_post_meta($product->ID, 'cate_type', true);
if (!empty($cate_type)) {
$cate_types = explode(',', $cate_type);
foreach ($cate_types as $type) {
$type = trim($type);
if (!empty($type) && !in_array($type, $unique_cate_types)) {
$unique_cate_types[] = $type;
}
}
}
}
if (!empty($category_order)) {
$category_order_array = explode(',', $category_order);
$category_order_array = array_map('trim', $category_order_array);
$unique_cate_types = array_filter($unique_cate_types, function($type) use ($category_order_array) {
return in_array($type, $category_order_array);
});
$unique_cate_types = array_intersect($category_order_array, $unique_cate_types);
}
$total_products = count($all_products);
?>
<style>
/* Custom scrollbar for horizontal scrolling elements */
.hide-scrollbar::-webkit-scrollbar {
display: none;
}
.hide-scrollbar {
-ms-overflow-style: none;
scrollbar-width: none;
}
/* Smooth Scrolling */
html {
scroll-behavior: smooth;
}
/* Card Hover Effects */
.product-card {
transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
position: relative; /* 确保 z-index 生效 */
z-index: 10;
margin-top: 8px;
}
.product-card:hover {
transform: translateY(-8px);
z-index: 30; /* 低于 filter 的 40 */
}
</style>
<main class="max-w-[1280px] mx-auto px-4 sm:px-6 lg:px-8 py-8 flex flex-col flex-1 min-h-screen">
<div class="max-w-4xl mb-10" data-aos="fade-right" data-aos-delay="200">
<h1 class="font-display text-[#111318] dark:text-white text-4xl md:text-5xl font-black leading-tight tracking-tight mb-4 bg-clip-text text-transparent bg-gradient-to-r from-gray-900 to-gray-600 dark:from-white dark:to-gray-400">
High-Performance Energy Storage
</h1>
<p class="text-[#5f6e8c] dark:text-gray-400 text-lg font-normal leading-relaxed max-w-2xl">
From residential backups to utility-scale grids. Explore our LFP and Solid-State battery solutions designed for maximum efficiency.
</p>
</div>
<div id="filter-sticky-wrapper" class="sticky top-[80px] z-40 mb-8 transition-all duration-300 -mx-4 px-4 sm:mx-0 sm:px-0 rounded-b-xl">
<div class="absolute inset-0 bg-background-light/95 dark:bg-background-dark/95 backdrop-blur-md transition-opacity duration-300 opacity-90 border-b border-transparent" id="filter-bg"></div>
<div class="relative max-w-[1280px] mx-auto py-3">
<div class="flex items-center justify-between mb-2 px-1">
<span class="text-[10px] font-extrabold tracking-widest text-gray-500 dark:text-gray-400 uppercase flex items-center gap-1">
<span class="material-symbols-outlined text-[14px]">&#xe429;</span>
Filter by Category
</span>
<div class="hidden sm:flex gap-2">
<span class="text-xs text-gray-400 font-mono" id="item-count-display">Showing <?php echo esc_html($total_products); ?> items</span>
</div>
</div>
<div class="relative group/filters">
<div class="absolute left-0 top-0 bottom-0 w-8 bg-gradient-to-r from-[#f8fcfa] dark:from-[#10221c] to-transparent z-10 pointer-events-none md:hidden transition-colors duration-300" id="mask-left"></div>
<div class="flex overflow-x-auto md:flex-wrap gap-3 py-2 -my-2 px-2 -mx-2 hide-scrollbar scroll-smooth snap-x items-center">
<button onclick="filterSelection('all', this)" class="filter-btn active snap-start shrink-0 relative flex items-center gap-2 pl-4 pr-5 h-10 rounded-full border transition-all duration-300 group" data-filter="all">
<span class="font-bold text-sm tracking-wide">All Systems</span>
<span class="count-badge flex items-center justify-center h-5 min-w-[20px] px-1.5 rounded-full text-[10px] font-bold"><?php echo esc_html($total_products); ?></span>
</button>
<?php foreach ($unique_cate_types as $cate_type): ?>
<?php
$cate_type_value = get_post_meta_by_key('cate_type_value', $cate_type);
$display_name = !empty($cate_type_value) ? $cate_type_value : $cate_type;
$count = 0;
foreach ($all_products as $product) {
$product_cate_type = get_post_meta($product->ID, 'cate_type', true);
if (!empty($product_cate_type) && strpos($product_cate_type, $cate_type) !== false) {
$count++;
}
}
?>
<button onclick="filterSelection('<?php echo esc_js($cate_type); ?>', this)" class="filter-btn snap-start shrink-0 flex items-center gap-2 pl-4 pr-4 h-10 rounded-full border border-[#e5e7eb] dark:border-[#374151] bg-white dark:bg-[#1f2937] text-[#5f6e8c] dark:text-gray-300 transition-all duration-300 hover:scale-105 active:scale-95 hover:shadow-lg hover:border-primary z-0 hover:z-10" data-filter="<?php echo esc_attr($cate_type); ?>">
<span class="font-medium text-sm"><?php echo esc_html($display_name); ?></span>
</button>
<?php endforeach; ?>
</div>
<div class="absolute right-0 top-0 bottom-0 w-12 bg-gradient-to-l from-[#f8fcfa] dark:from-[#10221c] to-transparent z-10 pointer-events-none md:hidden transition-colors duration-300" id="mask-right"></div>
</div>
</div>
</div>
<div id="initial-loader" class="py-12 w-full">
<div class="flex flex-col items-center justify-center space-y-4 w-full">
<div class="relative flex-shrink-0">
<div class="w-16 h-16 border-4 border-primary/20 border-t-primary rounded-full animate-spin"></div>
<div class="absolute inset-0 flex items-center justify-center">
<span class="material-symbols-outlined text-2xl text-primary animate-pulse">&#xe9d0;</span>
</div>
</div>
<div class="text-center">
<p class="text-gray-500 dark:text-gray-400 font-medium">Loading products...</p>
<p class="text-gray-400 dark:text-gray-500 text-sm mt-1">Please wait</p>
</div>
</div>
</div>
<div id="product-grid" class="columns-1 md:columns-2 lg:columns-3 gap-6 pb-12">
<?php if ($products_query->have_posts()): ?>
<?php while ($products_query->have_posts()): $products_query->the_post(); ?>
<?php
$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);
?>
<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 endwhile; ?>
<?php wp_reset_postdata(); ?>
<?php else: ?>
<div class="col-span-full text-center py-12">
<p class="text-gray-500 dark:text-gray-400">No products found.</p>
</div>
<?php endif; ?>
</div>
<?php if ($products_query->max_num_pages > 1): ?>
<div class="flex justify-center pt-8 pb-16" data-aos="zoom-in" data-aos-offset="50">
<button id="load-more-btn" class="relative group flex items-center justify-center px-8 py-3 rounded-full bg-primary/10 hover:bg-primary/20 dark:bg-primary/20 dark:hover:bg-primary/30 transition-all duration-300 active:scale-95" data-page="1" data-max-pages="<?php echo esc_attr($products_query->max_num_pages); ?>" data-per-page="<?php echo esc_attr($per_page); ?>">
<div class="absolute inset-0 rounded-full border border-primary opacity-20 animate-pulse group-hover:opacity-40"></div>
<span class="text-primary font-bold text-sm tracking-wide group-hover:scale-105 transition-transform">LOAD MORE PRODUCTS</span>
</button>
</div>
<?php endif; ?>
</main>
<script>
/**
* 产品列表状态管理器
* 负责管理产品列表的状态保存、恢复和清理
*/
const ProductListStateManager = {
// 状态键名常量
KEYS: {
GRID_HTML: 'products_grid_html',
SCROLL_POSITION: 'products_scroll_position',
CURRENT_PAGE: 'products_current_page',
CURRENT_CATEGORY: 'products_current_category',
LOAD_MORE_VISIBLE: 'products_load_more_visible',
NAVIGATED_FROM_LIST: 'products_navigated_from_list',
TIMESTAMP: 'products_state_timestamp'
},
// 状态过期时间30分钟
EXPIRY_TIME: 30 * 60 * 1000,
/**
* 保存当前状态
*/
save: function() {
console.log('[StateManager] Saving state...');
const grid = document.getElementById('product-grid');
const loadMoreBtn = document.getElementById('load-more-btn');
if (!grid) {
console.error('[StateManager] Grid element not found!');
return false;
}
console.log('[StateManager] Current global variables:', {
'window.currentPage': window.currentPage,
'window.currentCategory': window.currentCategory,
'currentPage (local)': currentPage,
'currentCategory (local)': currentCategory
});
const state = {
GRID_HTML: grid.innerHTML,
SCROLL_POSITION: window.scrollY,
CURRENT_PAGE: window.currentPage || currentPage || 1,
CURRENT_CATEGORY: window.currentCategory || currentCategory || 'all',
LOAD_MORE_VISIBLE: loadMoreBtn ? loadMoreBtn.style.display !== 'none' : false,
NAVIGATED_FROM_LIST: 'true',
TIMESTAMP: Date.now()
};
console.log('[StateManager] State to save:', state);
// 保存到 sessionStorage - 直接遍历 state 对象
Object.keys(state).forEach(key => {
const storageKey = this.KEYS[key.toUpperCase()] || this.KEYS[key];
const value = state[key];
console.log('[StateManager] Saving key:', key, '->', storageKey, '=', value);
if (value !== undefined && storageKey) {
sessionStorage.setItem(storageKey, typeof value === 'object' ? JSON.stringify(value) : value);
}
});
console.log('[StateManager] State saved:', {
productCount: grid.querySelectorAll('.product-card').length,
currentPage: state.currentPage,
currentCategory: state.currentCategory,
scrollPosition: state.scrollPosition,
loadMoreVisible: state.loadMoreVisible
});
return true;
},
/**
* 恢复状态
* @returns {boolean} 是否成功恢复
*/
restore: function() {
console.log('[StateManager] Restoring state...');
const gridHtml = sessionStorage.getItem(this.KEYS.GRID_HTML);
const navigatedFromList = sessionStorage.getItem(this.KEYS.NAVIGATED_FROM_LIST);
const timestamp = sessionStorage.getItem(this.KEYS.TIMESTAMP);
// 检查状态是否存在且未过期
if (!gridHtml || navigatedFromList !== 'true') {
console.log('[StateManager] No valid state to restore');
return false;
}
// 检查状态是否过期
if (timestamp && (Date.now() - parseInt(timestamp)) > this.EXPIRY_TIME) {
console.log('[StateManager] State expired, clearing...');
this.clear();
return false;
}
const grid = document.getElementById('product-grid');
if (!grid) {
console.error('[StateManager] Grid element not found!');
return false;
}
// 恢复产品列表
grid.innerHTML = gridHtml;
grid.style.display = 'block';
// 隐藏初始加载器
const initialLoader = document.getElementById('initial-loader');
if (initialLoader) {
initialLoader.style.display = 'none';
}
// 恢复全局变量和局部变量
window.currentPage = parseInt(sessionStorage.getItem(this.KEYS.CURRENT_PAGE)) || 1;
window.currentCategory = sessionStorage.getItem(this.KEYS.CURRENT_CATEGORY) || 'all';
// 同步更新局部变量
currentPage = window.currentPage;
currentCategory = window.currentCategory;
console.log('[StateManager] Restored variables:', {
'window.currentPage': window.currentPage,
'window.currentCategory': window.currentCategory,
'currentPage (local)': currentPage,
'currentCategory (local)': currentCategory
});
// 恢复加载更多按钮状态
const loadMoreBtn = document.getElementById('load-more-btn');
const loadMoreVisible = sessionStorage.getItem(this.KEYS.LOAD_MORE_VISIBLE) === 'true';
if (loadMoreBtn) {
const loadMoreContainer = loadMoreBtn.parentElement;
if (loadMoreVisible) {
loadMoreBtn.style.display = 'flex';
loadMoreBtn.disabled = false;
if (loadMoreContainer) loadMoreContainer.style.display = 'flex';
} else {
loadMoreBtn.style.display = 'none';
if (loadMoreContainer) loadMoreContainer.style.display = 'none';
}
}
// 恢复分类按钮样式
const savedCategory = sessionStorage.getItem(this.KEYS.CURRENT_CATEGORY);
if (savedCategory) {
const activeBtn = document.querySelector(`[data-filter="${savedCategory}"]`);
if (activeBtn) {
updateButtonStyles(activeBtn);
}
}
// 更新产品计数
const visibleCount = grid.querySelectorAll('.product-card').length;
updateItemCount(visibleCount);
// 刷新动画和图片
if (typeof AOS !== 'undefined') {
AOS.refresh();
}
if (typeof window.ImageLoader !== 'undefined' && typeof window.ImageLoader.scan === 'function') {
window.ImageLoader.scan();
}
console.log('[StateManager] State restored:', {
productCount: visibleCount,
currentPage: window.currentPage,
currentCategory: window.currentCategory
});
return true;
},
/**
* 恢复滚动位置
*/
restoreScrollPosition: function() {
const scrollPosition = sessionStorage.getItem(this.KEYS.SCROLL_POSITION);
if (scrollPosition) {
setTimeout(() => {
console.log('[StateManager] Restoring scroll position:', scrollPosition);
window.scrollTo({
top: parseInt(scrollPosition),
behavior: 'auto'
});
}, 100);
}
},
/**
* 清除所有状态
*/
clear: function() {
console.log('[StateManager] Clearing all state...');
Object.values(this.KEYS).forEach(key => {
sessionStorage.removeItem(key);
});
},
/**
* 检查是否有有效的状态
* @returns {boolean}
*/
hasValidState: function() {
const gridHtml = sessionStorage.getItem(this.KEYS.GRID_HTML);
const navigatedFromList = sessionStorage.getItem(this.KEYS.NAVIGATED_FROM_LIST);
const timestamp = sessionStorage.getItem(this.KEYS.TIMESTAMP);
console.log('[StateManager] Checking valid state:', {
gridHtml: gridHtml,
navigatedFromList: navigatedFromList,
timestamp: timestamp
});
if (!gridHtml || navigatedFromList !== 'true') {
return false;
}
// 检查是否过期
if (timestamp && (Date.now() - parseInt(timestamp)) > this.EXPIRY_TIME) {
this.clear();
return false;
}
return true;
}
};
// 全局变量
let currentCategory = 'all';
let currentPage = 1;
let perPage = 6;
let originalLoadMoreBtnContent = '';
const activeClass = "bg-[#111318] dark:bg-white text-white dark:text-[#111318] border-transparent shadow-lg shadow-gray-200 dark:shadow-none ring-2 ring-offset-2 ring-transparent";
const inactiveClass = "bg-white dark:bg-[#1f2937] text-[#5f6e8c] dark:text-gray-300 border-[#e5e7eb] dark:border-[#374151]";
/**
* 保存当前状态(兼容旧代码)
* @returns {boolean} 是否成功保存
*/
function saveState() {
return ProductListStateManager.save();
}
function updateButtonStyles(activeBtn) {
const filterBtns = document.querySelectorAll('.filter-btn');
filterBtns.forEach(btn => {
btn.className = btn.className.replace(activeClass, "").replace(inactiveClass, "");
btn.classList.add(...inactiveClass.split(" "));
const badge = btn.querySelector('.count-badge');
if(badge) {
badge.className = "count-badge hidden";
}
});
activeBtn.classList.remove(...inactiveClass.split(" "));
activeBtn.classList.add(...activeClass.split(" "));
const activeBadge = activeBtn.querySelector('.count-badge');
if(activeBadge) {
activeBadge.className = "count-badge flex items-center justify-center h-5 min-w-[20px] px-1.5 rounded-full bg-white/20 dark:bg-black/10 text-[10px] font-bold ml-auto";
}
}
function updateItemCount(count) {
const itemCountDisplay = document.getElementById('item-count-display');
if(itemCountDisplay) {
itemCountDisplay.textContent = `Showing ${count} items`;
}
}
function loadProducts(category, page = 1, append = false) {
const grid = document.getElementById('product-grid');
const loadMoreBtn = document.getElementById('load-more-btn');
const initialLoader = document.getElementById('initial-loader');
currentCategory = category;
window.currentCategory = category;
if (!append) {
if (initialLoader) {
initialLoader.style.display = 'flex';
}
grid.style.display = 'none';
grid.innerHTML = '';
} else if (loadMoreBtn) {
loadMoreBtn.innerHTML = `
<div class="flex items-center gap-2">
<span class="material-symbols-outlined animate-spin">&#xe9d0;</span>
<span>Loading...</span>
</div>
`;
loadMoreBtn.disabled = true;
}
const offset = (page - 1) * perPage;
console.log('[loadProducts] Request parameters:', {
category: category,
page: page,
perPage: perPage,
offset: offset,
append: append,
'currentPage (local)': currentPage,
'window.currentPage': window.currentPage
});
fetch('<?php echo admin_url('admin-ajax.php'); ?>', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: new URLSearchParams({
action: 'load_more_products',
offset: offset,
per_page: perPage,
category: category,
nonce: '<?php echo wp_create_nonce('load_more_products_nonce'); ?>'
})
})
.then(response => response.json())
.then(data => {
console.log('AJAX response:', data);
console.log('Append mode:', append);
if (data.success) {
console.log('Data success is true');
if (!append) {
grid.innerHTML = '';
grid.style.display = 'block';
if (initialLoader) {
initialLoader.style.display = 'none';
}
currentPage = 1;
window.currentPage = 1;
sessionStorage.setItem('products_current_page', 1);
sessionStorage.setItem('products_current_category', category);
}
data = data.data || {};
console.log('Products data:', data.products);
if (data.products && data.products.length > 0) {
console.log('Has products, adding to grid');
data.products.forEach(product => {
const tempDiv = document.createElement('div');
tempDiv.innerHTML = product.html;
const newCard = tempDiv.firstElementChild;
newCard.setAttribute('data-aos-delay', '0');
grid.appendChild(newCard);
});
if (typeof AOS !== 'undefined') {
AOS.refresh();
}
if (typeof window.ImageLoader !== 'undefined' && typeof window.ImageLoader.scan === 'function') {
window.ImageLoader.scan();
}
console.log('About to scroll, append:', append);
if (!append) {
console.log('Executing scroll logic');
setTimeout(() => {
const stickyWrapper = document.getElementById('filter-sticky-wrapper');
const headerOffset = 64 + (stickyWrapper ? stickyWrapper.offsetHeight : 60);
const gridRect = grid.getBoundingClientRect();
const targetPosition = gridRect.top + window.scrollY - headerOffset - 20;
console.log('Scrolling to position:', targetPosition, 'Current scroll:', window.scrollY, 'Grid top:', gridRect.top);
window.scrollTo({
top: targetPosition,
behavior: 'auto'
});
}, 150);
} else {
console.log('Skipping scroll, append mode');
}
const visibleCount = grid.querySelectorAll('.product-card').length;
updateItemCount(visibleCount);
console.log('Visible products:', visibleCount);
if (loadMoreBtn) {
const loadMoreContainer = loadMoreBtn.parentElement;
if (loadMoreContainer) {
loadMoreContainer.style.display = 'flex';
}
if (data.products.length < perPage) {
loadMoreBtn.style.display = 'none';
const loadMoreContainer = loadMoreBtn.parentElement;
if (loadMoreContainer) {
loadMoreContainer.style.display = 'none';
}
// 更新当前页码并保存状态
currentPage = page;
window.currentPage = page;
window.currentCategory = currentCategory;
sessionStorage.setItem('products_current_page', page);
console.log('Hide load more button - no more products, saving state');
saveState();
} else {
loadMoreBtn.style.display = 'flex';
loadMoreBtn.innerHTML = originalLoadMoreBtnContent;
loadMoreBtn.disabled = false;
currentPage = page;
window.currentPage = page;
window.currentCategory = currentCategory;
sessionStorage.setItem('products_current_page', page);
console.log('Show load more button - current page:', currentPage);
saveState();
}
}
} else if (!append) {
grid.style.display = 'block';
if (initialLoader) {
initialLoader.style.display = 'none';
}
grid.innerHTML = '<div class="col-span-full text-center py-12"><p class="text-gray-500 dark:text-gray-400">No products found.</p></div>';
updateItemCount(0);
if (loadMoreBtn) {
loadMoreBtn.style.display = 'none';
const loadMoreContainer = loadMoreBtn.parentElement;
if (loadMoreContainer) {
loadMoreContainer.style.display = 'none';
}
}
}
}
})
.catch(error => {
console.error('Error loading products:', error);
const initialLoader = document.getElementById('initial-loader');
if (!append) {
grid.style.display = 'block';
if (initialLoader) {
initialLoader.style.display = 'none';
}
grid.innerHTML = '<div class="col-span-full text-center py-12"><p class="text-red-500">Error loading products. Please try again.</p></div>';
}
if (loadMoreBtn && append) {
loadMoreBtn.innerHTML = originalLoadMoreBtnContent;
loadMoreBtn.disabled = false;
}
});
}
function filterSelection(category, clickedBtn) {
currentCategory = category;
window.currentCategory = category;
updateButtonStyles(clickedBtn);
const grid = document.getElementById('product-grid');
const loadMoreBtn = document.getElementById('load-more-btn');
if (loadMoreBtn) {
const loadMoreContainer = loadMoreBtn.parentElement;
if (loadMoreContainer) {
loadMoreContainer.style.display = 'flex';
}
}
loadProducts(category, 1, false);
}
document.addEventListener('DOMContentLoaded', function() {
const initialLoader = document.getElementById('initial-loader');
const grid = document.getElementById('product-grid');
window.currentPage = 1;
window.currentCategory = 'all';
if (initialLoader && grid) {
setTimeout(() => {
initialLoader.style.display = 'none';
if (typeof AOS !== 'undefined') {
AOS.refresh();
}
if (typeof window.ImageLoader !== 'undefined' && typeof window.ImageLoader.scan === 'function') {
window.ImageLoader.scan();
}
}, 500);
}
const loadMoreBtn = document.getElementById('load-more-btn');
if (loadMoreBtn) {
perPage = parseInt(loadMoreBtn.getAttribute('data-per-page')) || 6;
originalLoadMoreBtnContent = loadMoreBtn.innerHTML;
loadMoreBtn.addEventListener('click', function() {
const nextPage = currentPage + 1;
console.log('[Load More Button] Clicked:', {
'currentPage (local)': currentPage,
'window.currentPage': window.currentPage,
'nextPage': nextPage,
'currentCategory': currentCategory,
'window.currentCategory': window.currentCategory
});
loadProducts(currentCategory, nextPage, true);
});
}
/**
* 页面显示事件处理
* 处理从产品详情页返回的情况
*/
window.addEventListener('pageshow', function(event) {
console.log('[pageshow] Event triggered, persisted:', event.persisted);
// 检查是否有有效的状态需要恢复
if (ProductListStateManager.hasValidState()) {
console.log('[pageshow] Valid state found, restoring...');
// 恢复状态
const restored = ProductListStateManager.restore();
if (restored) {
// 恢复滚动位置
ProductListStateManager.restoreScrollPosition();
// 清除导航标记,避免重复恢复
sessionStorage.removeItem(ProductListStateManager.KEYS.NAVIGATED_FROM_LIST);
console.log('[pageshow] State restored successfully');
}
} else {
console.log('[pageshow] No valid state to restore');
// 如果不是从产品详情页返回,清除所有状态
console.log('[pageshow] Not navigated from list, clearing all states');
if (!ProductListStateManager.hasValidState()) {
ProductListStateManager.clear();
// 滚动到顶部
setTimeout(() => {
window.scrollTo({ top: 0, behavior: 'auto' });
}, 100);
}
}
});
const stickyEl = document.getElementById('filter-sticky-wrapper');
const filterBg = document.getElementById('filter-bg');
if (stickyEl && filterBg) {
const sentinel = document.createElement('div');
sentinel.setAttribute('id', 'sticky-sentinel');
stickyEl.parentNode.insertBefore(sentinel, stickyEl);
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (!entry.isIntersecting && entry.boundingClientRect.top < 0) {
filterBg.classList.add('border-gray-200', 'dark:border-gray-800', 'shadow-sm');
filterBg.classList.remove('border-transparent');
} else {
filterBg.classList.remove('border-gray-200', 'dark:border-gray-800', 'shadow-sm');
filterBg.classList.add('border-transparent');
}
});
}, {
threshold: 0,
rootMargin: '-72px 0px 0px 0px'
});
observer.observe(sentinel);
}
const navigatedFromList = sessionStorage.getItem('products_navigated_from_list');
const savedGridHtml = sessionStorage.getItem('products_grid_html');
const savedCategory = sessionStorage.getItem('products_current_category');
console.log('DOMContentLoaded - navigatedFromList:', navigatedFromList, 'savedGridHtml:', !!savedGridHtml);
if (navigatedFromList === 'true' && savedGridHtml) {
console.log('From product detail with saved HTML, skipping DOMContentLoaded initialization');
return;
}
if (navigatedFromList !== 'true' && !savedGridHtml) {
console.log('Normal page load - setting default button and clearing cache');
updateButtonStyles(document.querySelector('[data-filter="all"]'));
sessionStorage.clear();
} else if (savedCategory) {
console.log('Restoring category button:', savedCategory);
const activeBtn = document.querySelector(`[data-filter="${savedCategory}"]`);
if (activeBtn) {
updateButtonStyles(activeBtn);
}
}
if (!savedGridHtml) {
updateItemCount(document.querySelectorAll('.product-card').length);
}
document.addEventListener('click', function(event) {
const target = event.target;
console.log('[Click Event] Target:', target.tagName, target.className);
const link = target.closest('.product-detail-link');
if (link) {
console.log('[Click Event] Product detail link clicked:', link.href);
event.preventDefault();
event.stopPropagation();
console.log('[Click Event] Saving state before navigation...');
const saved = ProductListStateManager.save();
console.log('[Click Event] State saved, navigating to:', link.href);
window.location.href = link.href;
}
}, true);
});
</script>
Loading…
Cancel
Save