Files
orico-official-website/app/index/view/pc/public/header.html
jsasg b75a159d70
All checks were successful
Gitea Actions Official-website / deploy-dev (push) Successful in 4s
修复蒙版遮盖下划线
2026-04-17 12:28:21 +08:00

697 lines
29 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;
}
});
mhk.style.display = 'none';
// 恢复滚动
body.style.position = '';
body.style.top = '';
body.style.left = '';
body.style.right = '';
body.style.width = '';
// 恢复滚动位置
window.scrollTo(0, scrollTopPosition);
}
}
// 关闭所有导航下拉菜单
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);
// ========== 监听下拉菜单打开状态,自动控制蒙版 ==========
function initHeaderDropdown() {
// 获取所有下拉菜单
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 observeDropdown(dropdown) {
const observer = new MutationObserver(() => {
const isOpen = dropdown.style.opacity === '1';
if (isOpen) {
openOverlay();
} else {
let anyOpen = false;
allDropdowns.forEach(d => {
if (d.style.opacity === '1') anyOpen = true;
});
if (!anyOpen) {
closeOverlay();
}
}
});
observer.observe(dropdown, {
attributes: true,
attributeFilter: ['style']
});
}
// 为每个下拉菜单添加监听
allDropdowns.forEach(dropdown => {
observeDropdown(dropdown);
});
// 鼠标悬停控制下拉菜单显示/隐藏
const navItems = document.querySelectorAll('.header-nav-item');
navItems.forEach(item => {
const dropdown = item.querySelector('.header-dropdown');
if (!dropdown) return;
let timer = null;
let isHovering = false; // 增加悬停状态标记
// 显示下拉菜单的函数
const showDropdown = () => {
if (timer) clearTimeout(timer);
if (dropdown.style.opacity === '1') return;
dropdown.style.opacity = '1';
dropdown.style.transform = 'translateY(0)';
dropdown.style.pointerEvents = 'auto';
};
// 隐藏下拉菜单的函数
const hideDropdown = () => {
if (timer) clearTimeout(timer);
if (dropdown.style.opacity === '0') return;
dropdown.style.opacity = '0';
dropdown.style.transform = 'translateY(-1.25em)';
dropdown.style.pointerEvents = 'none';
};
item.addEventListener('mouseenter', () => {
isHovering = true;
clearTimeout(timer);
showDropdown();
});
item.addEventListener('mouseleave', (e) => {
isHovering = false;
// 检查鼠标是否移到了下拉菜单上
const relatedTarget = e.relatedTarget;
const isMovingToDropdown = dropdown.contains(relatedTarget);
if (isMovingToDropdown) {
// 如果移向下拉菜单,不清除,等待下拉菜单的 mouseenter
return;
}
timer = setTimeout(() => {
if (!isHovering && !dropdown.matches(':hover')) {
hideDropdown();
}
}, 100);
});
dropdown.addEventListener('mouseenter', () => {
isHovering = true;
clearTimeout(timer);
showDropdown();
});
dropdown.addEventListener('mouseleave', (e) => {
isHovering = false;
// 检查鼠标是否移回了导航项
const relatedTarget = e.relatedTarget;
const isMovingToNavItem = item.contains(relatedTarget);
if (isMovingToNavItem) {
return;
}
timer = setTimeout(() => {
if (!isHovering && !item.matches(':hover')) {
hideDropdown();
}
}, 100);
});
});
}
// 初始化(在 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>