Files
orico-official-website/app/index/view/pc/public/header.html
jsasg 456b2ede8a
All checks were successful
Gitea Actions Official-website / deploy-dev (push) Successful in 3s
产品列表图片间距
2026-04-17 10:31:33 +08:00

763 lines
32 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<link rel="stylesheet" href="__CSS__/header.css">
<div class="header" >
<!-- 导航外容器1920px宽下拉框基于此定位 -->
<div class="header-nav-outer" >
<!-- 顶部导航栏 -->
<div class="header-nav-bar">
<div style="display:flex;align-items:center">
<a href="/" style="display:flex;align-items:center">
<img src="__IMAGES__/logo.png" alt="orico" class="header-log">
</a>
</div>
<div class="header-nav-items">
{if condition="!empty($header_categorys)"}
<div class="header-nav-item" >
<div class="header-nav-title">{:lang_i18n('产品列表')}</div>
<!-- style=" opacity: 1;" -->
<div class="header-dropdown" style=" opacity: 1;">
<div class="header-dropdown-tabs">
{volist name="header_categorys" id="vo" key="idx"}
<a href="{:url('product/category', ['id' => $vo.id])}" class="header-tab-item {if condition="$idx == 1"}active{/if}" data-tab="tag-{$vo.id}">{$vo.name}</a>
{/volist}
</div>
{volist name="header_categorys" id="vo" key="idx"}
<div class="header-dropdown-content header-tab-content {if condition="$idx == 1"}active{/if}" id="tag-{$vo.id}">
<div class="header-dropdown-category">
{if condition="!empty($vo.children)"}
{volist name="vo.children" id="vc"}
<div class="header-category-box">
{volist name="vc" id="vcc"}
<div class="header-category-block">
<div class="header-category-title">
<a href="{:url('product/subcategory', ['id' => $vcc.id])}" target="_self">
{$vcc.name}
</a>
</div>
<ul class="header-category-list">
{if condition="!empty($vcc.children)"}
{volist name="vcc.children" id="vccc" length="5"}
<li class="header-category-item">
<a href="{:url('product/subcategory', ['id' => $vccc.id])}" target="_self">
{$vccc.name}
</a>
</li>
{/volist}
{/if}
</ul>
</div>
{/volist}
</div>
{/volist}
{/if}
</div>
<div class="header-dropdown-products">
{if condition="!empty($vo.recommends)"}
{volist name="vo.recommends" id="recommend"}
<div class="header-product-card">
<a href="{$recommend.link}">
<div class="header-product-img">
<img src="{$recommend.image}" alt="">
</div>
<div class="header-product-name">{$recommend.title}</div>
</a>
</div>
{/volist}
{/if}
</div>
</div>
{/volist}
</div>
</div>
{/if}
{if condition="!empty($header_navigation)"}
{volist name="header_navigation" id="nav"}
<div class="header-nav-item">
{if condition="empty($nav.children)"}
<div class="header-nav-title">
<a href="{$nav.link}" target="{$nav.blank==1?'_blank':'_self'}">{$nav.name}</a>
</div>
{else /}
<div class="header-nav-title">{$nav.name}</div>
<div class="header-dropdown">
<div class="header-dropdown-content1">
{volist name="nav.children" id="child"}
<div class="header-product-card-1">
<a href="{$child.link}" target="{$child.blank==1?'_blank':'_self'}">
<div class="header-product-img-1">
<img src="{$child.image}" alt="">
</div>
<div class="header-product-title-1">{$child.name}</div>
<div class="header-product-name-1">{$child.desc}</div>
</a>
</div>
{/volist}
</div>
</div>
{/if}
</div>
{/volist}
{/if}
</div>
<!-- 右侧功能按钮 -->
<div class="header-nav-actions">
<div class="header-search-wrapper">
<span class="header-nav-btn">
<img src="__IMAGES__/s1.png" alt="" style="width: 20px;height: 20px;">
</span>
<div class="header-search-dropdown" id="searchDropdown">
<span class="header-search-dropdown-delete-icon"></span>
<div class="header-search-input-wrapper">
<input type="text" class="header-search-input" placeholder="{:lang_i18n('搜索产品、分类...')}">
<button class="header-search-submit">{:lang_i18n('搜索')}</button>
</div>
<div class="header-search-history" id="searchHistory">
<div class="header-history-title">
<span>{:lang_i18n('最近搜索')}</span>
<span class="header-clear-history" id="clearHistory">{:lang_i18n('清空')}</span>
</div>
<div class="header-history-list" id="historyList"></div>
</div>
<div class="header-hot-products">
<div class="header-hot-title">{:lang_i18n('热销产品')}</div>
<div class="header-hot-product-list">
{if condition="!empty($header_hot_products)"}
{volist name="header_hot_products" id="pro"}
<div class="header-hot-product-item" data-keyword="keyword-{$pro.id}">
<div class="header-hot-product-img">
<a href="{:url('product/detail', ['id' => $pro.id])}">
<img src="{:thumb($pro.cover_image)}" alt="">
</a>
</div>
<div class="header-hot-product-name">{$pro.name}</div>
</div>
{/volist}
{/if}
</div>
</div>
</div>
</div>
<div class="header-lang-wrapper" >
<span class="header-nav-btn">
<img src="__IMAGES__/l1.png" alt="" style="width: 20px;height:20px">
</span>
<div class="header-lang-dropdown" id="langDropdown">
<span class="header-lang-dropdown-delete-icon"></span>
{volist name="header_languages" id="vo"}
<a href="{$vo.lang_url}" class="header-lang-item" data-lang="zh-CN" target="_self">
<img src="{$vo.lang_icon}" alt="">
{eq name=":cookie('think_lang')" value="zh-cn"}
<span class="header-lang-code">{$vo.country_zh_name}</span>
<span class="header-lang-name">{$vo.lang_name}</span>
{else}
<span class="header-lang-code">{$vo.country_en_name}</span>
<span class="header-lang-name-en">{$vo.lang_en_name}</span>
{/eq}
</a>
{/volist}
</div>
</div>
<div class="header-buy-wrapper">
<button class="header-buy-btn" style="line-height: 1;">
<img src="__IMAGES__/g1.png" alt="" style="margin-right:5px;width: 14px;height: 14px;">
{:lang_i18n('购买')}
</button>
<!-- <img src="__IMAGES__/gm.png" alt="" style="margin-right: 3px;"> -->
</div>
</div>
</div>
<!-- 购买下拉框 -->
<div class="header-buy-dropdown" id="buyDropdown">
<div class="header-buy-dropdown-content">
{if condition="!empty($header_mall_entrance)"}
{volist name="header_mall_entrance" id="ma"}
<a class="header-buy-product-card" target="_self" href="{$ma.link}">
<div class="header-buy-product-img">
<img class="header-default-img" src="{$ma.image}" alt="{$ma.name}">
{if condition="!empty($ma.hover_image)"}
<img class="header-hover-img" src="{$ma.hover_image}" alt="{$ma.name}">
{/if}
</div>
<div class="header-buy-product-title">{$ma.name}</div>
</a>
{/volist}
{/if}
</div>
</div>
</div>
</div>
<div style="width: 100vw;height: 64px;"></div>
<div id="mhk"></div>
<script>
// 获取所有包含商品卡片的元素
const productCards = document.querySelectorAll('.header-buy-product-card');
productCards.forEach(card => {
// 获取卡片内的图片容器和两张图片
const imgContainer = card.querySelector('.header-buy-product-img');
const defaultImg = imgContainer?.querySelector('.header-default-img');
const hoverImg = imgContainer?.querySelector('.header-hover-img');
// 检查悬浮图是否存在因为HTML中用了if判断所以可能有也可能没有这个元素
const hasHoverImg = hoverImg !== null;
// 如果没有悬浮图,不需要任何交互,直接返回
if (!hasHoverImg) return;
// 初始状态确保普通图显示,悬浮图隐藏
defaultImg.style.opacity = '1';
hoverImg.style.opacity = '0';
// 鼠标移入事件:显示悬浮图,隐藏普通图
card.addEventListener('mouseenter', () => {
defaultImg.style.opacity = '0';
hoverImg.style.opacity = '1';
});
// 鼠标移出事件:恢复普通图,隐藏悬浮图
card.addEventListener('mouseleave', () => {
defaultImg.style.opacity = '1';
hoverImg.style.opacity = '0';
});
});
// 产品列表在hover复位tabs选择
const productNavContainer = document.querySelector('.header-nav-item:first-child');
if (productNavContainer) {
productNavContainer.addEventListener('mouseleave', () => {
// 延迟执行,确保下拉菜单已经隐藏
setTimeout(() => {
const tabs = document.querySelectorAll('.header-tab-item');
const contents = document.querySelectorAll('.header-tab-content');
// 重置到第一个tab
if (tabs.length > 0 && tabs[0]) {
tabs.forEach(tab => tab.classList.remove('active'));
contents.forEach(content => content.classList.remove('active'));
tabs[0].classList.add('active');
const firstContentId = tabs[0].getAttribute('data-tab');
const firstContent = document.getElementById(firstContentId);
if (firstContent) firstContent.classList.add('active');
}
}, 350);
});
}
const tabItems1 = document.querySelectorAll('.header-tab-item');
const tabContents = document.querySelectorAll('.header-tab-content');
tabItems1.forEach(tab => {
tab.addEventListener('mouseenter', () => {
tabItems1.forEach(item => item.classList.remove('active'));
tab.classList.add('active');
const tabId = tab.getAttribute('data-tab');
tabContents.forEach(content => {
content.classList.remove('active');
if (content.id === tabId) {
content.classList.add('active');
}
});
});
});
let searchHistory = JSON.parse(localStorage.getItem('searchHistory') || '[]');
function renderHistory() {
const historyList = document.getElementById('historyList');
const historySection = document.getElementById('searchHistory');
if (searchHistory.length === 0) {
if (historySection) historySection.style.display = 'none';
return;
}
if (historySection) historySection.style.display = 'block';
if (historyList) {
historyList.innerHTML = searchHistory.map((item, index) => `
<div class="header-history-item" data-keyword="${item}">
<span>${item}</span>
<span class="header-delete-icon" data-index="${index}">✕</span>
</div>
`).join('');
}
document.querySelectorAll('.header-history-item').forEach(item => {
const keyword = item.getAttribute('data-keyword');
const deleteBtn = item.querySelector('.header-delete-icon');
item.addEventListener('click', (e) => {
if (e.target === deleteBtn) return;
performSearch(keyword);
});
if (deleteBtn) {
deleteBtn.addEventListener('click', (e) => {
e.stopPropagation();
const index = parseInt(deleteBtn.getAttribute('data-index'));
searchHistory.splice(index, 1);
localStorage.setItem('searchHistory', JSON.stringify(searchHistory));
renderHistory();
});
}
});
}
function addToHistory(keyword) {
if (!keyword.trim()) return;
searchHistory = searchHistory.filter(item => item !== keyword);
searchHistory.unshift(keyword);
if (searchHistory.length > 10) searchHistory.pop();
localStorage.setItem('searchHistory', JSON.stringify(searchHistory));
renderHistory();
}
const clearHistoryBtn = document.getElementById('clearHistory');
if (clearHistoryBtn) {
clearHistoryBtn.addEventListener('click', () => {
searchHistory = [];
localStorage.setItem('searchHistory', JSON.stringify(searchHistory));
renderHistory();
});
}
function performSearch(keyword) {
if (keyword.trim()) {
addToHistory(keyword);
window.location.href = "{:url('product/search')}?keywords=" + encodeURIComponent(keyword);
if (searchDropdown) searchDropdown.classList.remove('show');
if (searchInput) searchInput.value = '';
}
}
const searchBtn = document.querySelector('.header-search-wrapper .header-nav-btn');
const searchDropdown = document.getElementById('searchDropdown');
const searchInput = document.querySelector('.header-search-input');
const searchSubmit = document.querySelector('.header-search-submit');
const langDropdown = document.getElementById('langDropdown');
const buyDropdown = document.getElementById('buyDropdown');
const mhk = document.getElementById('mhk');
const body = document.body;
const langCloseBtn = document.querySelector('.header-lang-dropdown-delete-icon');
const searchCloseBtn = document.querySelector('.header-search-dropdown-delete-icon');
// 保存滚动位置
let scrollTopPosition = 0;
// 打开蒙版层(禁止滚动,不抖动)
function openOverlay() {
if (mhk && mhk.style.display !== 'block') {
// 保存当前滚动位置
scrollTopPosition = window.pageYOffset || document.documentElement.scrollTop;
mhk.style.display = 'block';
// 禁止滚动,保持位置
body.style.position = 'fixed';
body.style.top = `-${scrollTopPosition}px`;
body.style.left = '0';
body.style.right = '0';
body.style.width = '100%';
}
}
// 关闭蒙版层(恢复滚动)
function closeOverlay() {
if (mhk && mhk.style.display === 'block') {
const isBuyOpen = buyDropdown && buyDropdown.classList.contains('show');
const isSearchOpen = searchDropdown && searchDropdown.classList.contains('show');
const isLangOpen = langDropdown && langDropdown.classList.contains('show');
// 检查是否有任何导航下拉菜单打开
let hasNavOpen = false;
document.querySelectorAll('.header-dropdown').forEach(dropdown => {
const style = window.getComputedStyle(dropdown);
if (style.opacity === '1') {
hasNavOpen = true;
}
});
if (!isBuyOpen && !isSearchOpen && !isLangOpen && !hasNavOpen) {
mhk.style.display = 'none';
// 恢复滚动
body.style.position = '';
body.style.top = '';
body.style.left = '';
body.style.right = '';
body.style.width = '';
// 恢复滚动位置
window.scrollTo(0, scrollTopPosition);
}
}
}
// ========== header-dropdown 导航下拉菜单打开时显示蒙版 ==========
function initNavDropdownOverlay() {
const navItems = document.querySelectorAll('.header-nav-item');
let hideTimer = null;
navItems.forEach(item => {
const dropdown = item.querySelector('.header-dropdown');
if (!dropdown) return;
// 鼠标移入导航项
item.addEventListener('mouseenter', () => {
if (hideTimer) clearTimeout(hideTimer);
openOverlay();
});
// 鼠标移出导航项
item.addEventListener('mouseleave', () => {
hideTimer = setTimeout(() => {
const isHoveringDropdown = dropdown && dropdown.matches(':hover');
if (!isHoveringDropdown) {
const isBuyOpen = buyDropdown && buyDropdown.classList.contains('show');
const isSearchOpen = searchDropdown && searchDropdown.classList.contains('show');
const isLangOpen = langDropdown && langDropdown.classList.contains('show');
if (!isBuyOpen && !isSearchOpen && !isLangOpen) {
closeOverlay();
}
}
}, 100);
});
// 鼠标移入下拉菜单
dropdown.addEventListener('mouseenter', () => {
if (hideTimer) clearTimeout(hideTimer);
openOverlay();
});
// 鼠标移出下拉菜单
dropdown.addEventListener('mouseleave', () => {
hideTimer = setTimeout(() => {
const isHoveringNav = item && item.matches(':hover');
if (!isHoveringNav) {
const isBuyOpen = buyDropdown && buyDropdown.classList.contains('show');
const isSearchOpen = searchDropdown && searchDropdown.classList.contains('show');
const isLangOpen = langDropdown && langDropdown.classList.contains('show');
if (!isBuyOpen && !isSearchOpen && !isLangOpen) {
closeOverlay();
}
}
}, 100);
});
});
}
// 关闭所有导航下拉菜单
function closeAllNavDropdowns() {
document.querySelectorAll('.header-dropdown').forEach(dropdown => {
dropdown.style.opacity = '';
dropdown.style.transform = '';
dropdown.style.pointerEvents = '';
});
}
// 语言关闭按钮
if (langCloseBtn) {
langCloseBtn.addEventListener('click', (e) => {
e.stopPropagation();
if (langDropdown) langDropdown.classList.remove('show');
closeOverlay();
});
}
// 搜索关闭按钮
if (searchCloseBtn) {
searchCloseBtn.addEventListener('click', (e) => {
e.stopPropagation();
if (searchDropdown) searchDropdown.classList.remove('show');
closeOverlay();
});
}
// 鼠标移入导航项时,关闭其他弹窗
const navItems = document.querySelectorAll('.header-nav-item');
navItems.forEach(item => {
item.addEventListener('mouseenter', () => {
if (buyDropdown) buyDropdown.classList.remove('show');
if (langDropdown) langDropdown.classList.remove('show');
if (searchDropdown) searchDropdown.classList.remove('show');
});
});
// 搜索按钮点击
if (searchBtn && searchDropdown) {
searchBtn.addEventListener('click', (e) => {
e.stopPropagation();
if (langDropdown) langDropdown.classList.remove('show');
if (buyDropdown) buyDropdown.classList.remove('show');
searchDropdown.classList.toggle('show');
if (searchDropdown.classList.contains('show')) {
renderHistory();
openOverlay();
} else {
closeOverlay();
}
});
}
if (searchSubmit) {
searchSubmit.addEventListener('click', () => {
performSearch(searchInput.value);
});
}
if (searchInput) {
searchInput.addEventListener('keypress', (e) => {
if (e.key === 'Enter') {
performSearch(searchInput.value);
}
});
}
const hotProducts = document.querySelectorAll('.header-hot-product-item');
hotProducts.forEach(product => {
product.addEventListener('click', () => {
const keyword = product.getAttribute('data-keyword');
if (keyword) performSearch(keyword);
});
});
// 语言按钮点击
const langBtn = document.querySelector('.header-lang-wrapper .header-nav-btn');
if (langBtn && langDropdown) {
langBtn.addEventListener('click', (e) => {
e.stopPropagation();
if (searchDropdown) searchDropdown.classList.remove('show');
if (buyDropdown) buyDropdown.classList.remove('show');
langDropdown.classList.toggle('show');
if (langDropdown.classList.contains('show')) {
openOverlay();
} else {
closeOverlay();
}
});
}
// 购买按钮点击
const buyWrapper = document.querySelector('.header-buy-wrapper');
if (buyWrapper && buyDropdown) {
buyWrapper.addEventListener('click', () => {
buyDropdown.classList.toggle('show');
if (buyDropdown.classList.contains('show')) {
openOverlay();
} else {
closeOverlay();
}
});
}
// 全局点击关闭
document.addEventListener('click', (e) => {
if (!e.target.closest('.header-search-wrapper')) {
if (searchDropdown) searchDropdown.classList.remove('show');
}
if (!e.target.closest('.header-lang-wrapper')) {
if (langDropdown) langDropdown.classList.remove('show');
}
if (!e.target.closest('.header-buy-wrapper')) {
if (buyDropdown) buyDropdown.classList.remove('show');
}
// 关闭所有导航下拉菜单
if (!e.target.closest('.header-nav-item')) {
closeAllNavDropdowns();
closeOverlay();
}
});
// 阻止弹窗冒泡
if (searchDropdown) searchDropdown.addEventListener('click', (e) => e.stopPropagation());
if (langDropdown) langDropdown.addEventListener('click', (e) => e.stopPropagation());
if (buyDropdown) buyDropdown.addEventListener('click', (e) => e.stopPropagation());
// 蒙版层点击关闭
if (mhk) {
mhk.addEventListener('click', () => {
if (searchDropdown) searchDropdown.classList.remove('show');
if (langDropdown) langDropdown.classList.remove('show');
if (buyDropdown) buyDropdown.classList.remove('show');
closeAllNavDropdowns();
closeOverlay();
});
}
// 监听弹窗状态变化关闭蒙版
function setupDropdownObserver(dropdown) {
if (!dropdown) return;
const observer = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
if (mutation.attributeName === 'class') {
if (!dropdown.classList.contains('show')) {
closeOverlay();
}
}
});
});
observer.observe(dropdown, { attributes: true });
}
setupDropdownObserver(buyDropdown);
setupDropdownObserver(searchDropdown);
setupDropdownObserver(langDropdown);
// ========== header-dropdown JS 控制版本(带防抖) ==========
function initHeaderDropdown() {
const navItems = document.querySelectorAll('.header-nav-item');
let hoverTimer = null;
let leaveTimer = null;
let currentOpenDropdown = null;
// 获取所有下拉菜单并设置初始状态
const allDropdowns = document.querySelectorAll('.header-dropdown');
allDropdowns.forEach(dropdown => {
dropdown.style.opacity = '0';
dropdown.style.transform = 'translateY(-1.25em)';
dropdown.style.pointerEvents = 'none';
dropdown.style.transition = 'opacity 0.3s ease, transform 0.3s ease';
});
// 显示下拉菜单
function showDropdown(dropdown) {
if (!dropdown) return;
// 关闭当前打开的
if (currentOpenDropdown && currentOpenDropdown !== dropdown) {
hideDropdown(currentOpenDropdown);
}
dropdown.style.opacity = '1';
dropdown.style.transform = 'translateY(0)';
dropdown.style.pointerEvents = 'auto';
currentOpenDropdown = dropdown;
}
// 隐藏下拉菜单
function hideDropdown(dropdown) {
if (!dropdown) return;
dropdown.style.opacity = '0';
dropdown.style.transform = 'translateY(-1.25em)';
dropdown.style.pointerEvents = 'none';
if (currentOpenDropdown === dropdown) {
currentOpenDropdown = null;
}
}
// 隐藏所有下拉菜单
function hideAllDropdowns() {
allDropdowns.forEach(dropdown => {
dropdown.style.opacity = '0';
dropdown.style.transform = 'translateY(-1.25em)';
dropdown.style.pointerEvents = 'none';
});
currentOpenDropdown = null;
}
navItems.forEach(item => {
const dropdown = item.querySelector('.header-dropdown');
if (!dropdown) return;
// 鼠标移入导航项
item.addEventListener('mouseenter', () => {
// 清除离开定时器
if (leaveTimer) clearTimeout(leaveTimer);
if (hoverTimer) clearTimeout(hoverTimer);
// 防抖延迟100ms再显示避免频繁触发
hoverTimer = setTimeout(() => {
// 关闭其他弹窗(搜索、语言、购买)
if (searchDropdown) searchDropdown.classList.remove('show');
if (langDropdown) langDropdown.classList.remove('show');
if (buyDropdown) buyDropdown.classList.remove('show');
showDropdown(dropdown);
// 打开蒙版层
if (typeof openOverlay === 'function') openOverlay();
}, 100);
});
// 鼠标移出导航项
item.addEventListener('mouseleave', () => {
// 清除移入定时器
if (hoverTimer) clearTimeout(hoverTimer);
// 延迟300ms再隐藏给用户移动到下拉菜单的时间
leaveTimer = setTimeout(() => {
// 检查鼠标是否在下拉菜单上
const isHoveringDropdown = dropdown.matches(':hover');
if (!isHoveringDropdown) {
hideDropdown(dropdown);
// 关闭蒙版层
if (typeof closeOverlay === 'function') closeOverlay();
}
}, 300);
});
// 鼠标移入下拉菜单
dropdown.addEventListener('mouseenter', () => {
if (leaveTimer) clearTimeout(leaveTimer);
showDropdown(dropdown);
});
// 鼠标移出下拉菜单
dropdown.addEventListener('mouseleave', () => {
leaveTimer = setTimeout(() => {
const isHoveringNav = item.matches(':hover');
if (!isHoveringNav) {
hideDropdown(dropdown);
// 关闭蒙版层
if (typeof closeOverlay === 'function') closeOverlay();
}
}, 200);
});
});
// 点击其他地方关闭所有下拉菜单
document.addEventListener('click', (e) => {
if (!e.target.closest('.header-nav-item')) {
hideAllDropdowns();
if (typeof closeOverlay === 'function') closeOverlay();
}
});
// 暴露方法供外部调用
window.headerDropdown = {
hideAll: hideAllDropdowns,
show: showDropdown,
hide: hideDropdown
};
}
// 初始化(在 DOM 加载完成后执行)
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', initHeaderDropdown);
} else {
initHeaderDropdown();
}
// 页面卸载时恢复滚动
window.addEventListener('beforeunload', () => {
if (body) {
body.style.position = '';
body.style.top = '';
body.style.left = '';
body.style.right = '';
body.style.width = '';
}
});
// 初始化导航下拉菜单蒙版层
initNavDropdownOverlay();
// 初始化渲染
renderHistory();
closeOverlay();
</script>