25 Commits
dev ... v1.3.1

Author SHA1 Message Date
2b2dc2021a Merge branch 'dev' 2026-04-16 15:58:40 +08:00
654caf58c2 Merge branch 'dev' 2026-04-16 15:04:09 +08:00
49240893b5 Merge branch 'dev' 2026-01-13 17:31:40 +08:00
f4646f1e3a Merge branch 'dev' 2025-12-31 17:07:35 +08:00
624d7fde2f Merge branch 'master' of http://gitea.f2b211.com/jsasg/orico-official-website 2025-12-31 17:00:00 +08:00
a85f2c1b3a Merge branch 'dev' 2025-12-31 16:55:53 +08:00
67016c4e9a Merge branch 'dev' 2025-12-31 15:00:04 +08:00
12bc6aeee7 Merge branch 'dev' 2025-12-31 11:49:53 +08:00
24e5554bc4 Merge branch 'dev' 2025-12-22 10:15:48 +08:00
c767c20641 Merge branch 'dev' 2025-12-20 16:04:57 +08:00
2c85df4a98 Merge branch 'dev' 2025-12-05 09:36:52 +08:00
88a91f3136 删除注释 2025-12-04 10:27:05 +08:00
5fd603cbc6 底部样式 2025-12-04 10:25:06 +08:00
b92753c822 底部 2025-12-04 10:22:56 +08:00
ddd578eb08 Merge branch 'dev' 2025-12-03 17:56:52 +08:00
1cdd0536b9 Merge branch 'font' 2025-12-01 15:46:23 +08:00
9cc6dc3cd9 Merge branch 'dev' 2025-11-28 16:23:35 +08:00
4d25f6fec8 Merge branch 'dev' 2025-11-28 15:46:00 +08:00
2764ce3b86 Merge branch 'dev' 2025-11-28 15:36:31 +08:00
7cb270b313 Merge branch 'dev' 2025-11-28 15:23:45 +08:00
86ffcb99ac Merge branch 'dev' 2025-11-28 14:51:46 +08:00
c476193002 Merge branch 'dev' 2025-11-28 14:43:34 +08:00
5643faad94 Merge branch 'dev' 2025-11-28 14:36:46 +08:00
989f6c25a0 refactor: 修改..gitignore 2025-11-28 14:35:35 +08:00
2e5103b19a Initial commit 2025-11-28 14:33:22 +08:00
3 changed files with 758 additions and 354 deletions

208
LICENSE Normal file
View File

@@ -0,0 +1,208 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION,
AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction, and distribution
as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by the copyright
owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all other entities
that control, are controlled by, or are under common control with that entity.
For the purposes of this definition, "control" means (i) the power, direct
or indirect, to cause the direction or management of such entity, whether
by contract or otherwise, or (ii) ownership of fifty percent (50%) or more
of the outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity exercising permissions
granted by this License.
"Source" form shall mean the preferred form for making modifications, including
but not limited to software source code, documentation source, and configuration
files.
"Object" form shall mean any form resulting from mechanical transformation
or translation of a Source form, including but not limited to compiled object
code, generated documentation, and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or Object form,
made available under the License, as indicated by a copyright notice that
is included in or attached to the work (an example is provided in the Appendix
below).
"Derivative Works" shall mean any work, whether in Source or Object form,
that is based on (or derived from) the Work and for which the editorial revisions,
annotations, elaborations, or other modifications represent, as a whole, an
original work of authorship. For the purposes of this License, Derivative
Works shall not include works that remain separable from, or merely link (or
bind by name) to the interfaces of, the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including the original version
of the Work and any modifications or additions to that Work or Derivative
Works thereof, that is intentionally submitted to Licensor for inclusion in
the Work by the copyright owner or by an individual or Legal Entity authorized
to submit on behalf of the copyright owner. For the purposes of this definition,
"submitted" means any form of electronic, verbal, or written communication
sent to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems, and
issue tracking systems that are managed by, or on behalf of, the Licensor
for the purpose of discussing and improving the Work, but excluding communication
that is conspicuously marked or otherwise designated in writing by the copyright
owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity on behalf
of whom a Contribution has been received by Licensor and subsequently incorporated
within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of this
License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive,
no-charge, royalty-free, irrevocable copyright license to reproduce, prepare
Derivative Works of, publicly display, publicly perform, sublicense, and distribute
the Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of this License,
each Contributor hereby grants to You a perpetual, worldwide, non-exclusive,
no-charge, royalty-free, irrevocable (except as stated in this section) patent
license to make, have made, use, offer to sell, sell, import, and otherwise
transfer the Work, where such license applies only to those patent claims
licensable by such Contributor that are necessarily infringed by their Contribution(s)
alone or by combination of their Contribution(s) with the Work to which such
Contribution(s) was submitted. If You institute patent litigation against
any entity (including a cross-claim or counterclaim in a lawsuit) alleging
that the Work or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses granted to You
under this License for that Work shall terminate as of the date such litigation
is filed.
4. Redistribution. You may reproduce and distribute copies of the Work or
Derivative Works thereof in any medium, with or without modifications, and
in Source or Object form, provided that You meet the following conditions:
(a) You must give any other recipients of the Work or Derivative Works a copy
of this License; and
(b) You must cause any modified files to carry prominent notices stating that
You changed the files; and
(c) You must retain, in the Source form of any Derivative Works that You distribute,
all copyright, patent, trademark, and attribution notices from the Source
form of the Work, excluding those notices that do not pertain to any part
of the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its distribution,
then any Derivative Works that You distribute must include a readable copy
of the attribution notices contained within such NOTICE file, excluding those
notices that do not pertain to any part of the Derivative Works, in at least
one of the following places: within a NOTICE text file distributed as part
of the Derivative Works; within the Source form or documentation, if provided
along with the Derivative Works; or, within a display generated by the Derivative
Works, if and wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and do not modify the
License. You may add Your own attribution notices within Derivative Works
that You distribute, alongside or as an addendum to the NOTICE text from the
Work, provided that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and may provide
additional or different license terms and conditions for use, reproduction,
or distribution of Your modifications, or for any such Derivative Works as
a whole, provided Your use, reproduction, and distribution of the Work otherwise
complies with the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise, any
Contribution intentionally submitted for inclusion in the Work by You to the
Licensor shall be under the terms and conditions of this License, without
any additional terms or conditions. Notwithstanding the above, nothing herein
shall supersede or modify the terms of any separate license agreement you
may have executed with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade names,
trademarks, service marks, or product names of the Licensor, except as required
for reasonable and customary use in describing the origin of the Work and
reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or agreed to
in writing, Licensor provides the Work (and each Contributor provides its
Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied, including, without limitation, any warranties
or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR
A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness
of using or redistributing the Work and assume any risks associated with Your
exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory, whether
in tort (including negligence), contract, or otherwise, unless required by
applicable law (such as deliberate and grossly negligent acts) or agreed to
in writing, shall any Contributor be liable to You for damages, including
any direct, indirect, special, incidental, or consequential damages of any
character arising as a result of this License or out of the use or inability
to use the Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all other commercial
damages or losses), even if such Contributor has been advised of the possibility
of such damages.
9. Accepting Warranty or Additional Liability. While redistributing the Work
or Derivative Works thereof, You may choose to offer, and charge a fee for,
acceptance of support, warranty, indemnity, or other liability obligations
and/or rights consistent with this License. However, in accepting such obligations,
You may act only on Your own behalf and on Your sole responsibility, not on
behalf of any other Contributor, and only if You agree to indemnify, defend,
and hold each Contributor harmless for any liability incurred by, or claims
asserted against, such Contributor by reason of your accepting any such warranty
or additional liability. END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following boilerplate
notice, with the fields enclosed by brackets "[]" replaced with your own identifying
information. (Don't include the brackets!) The text should be enclosed in
the appropriate comment syntax for the file format. We also recommend that
a file or class name and description of purpose be included on the same "printed
page" as the copyright notice for easier identification within third-party
archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@@ -11,10 +11,9 @@
</div>
<div class="header-nav-items">
{if condition="!empty($header_categorys)"}
<div class="header-nav-item" >
<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" >
<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>
@@ -191,41 +190,40 @@
</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');
// 获取卡片内的图片容器和两张图片
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;
// 检查悬浮图是否存在因为HTML中用了if判断所以可能有也可能没有这个元素
const hasHoverImg = hoverImg !== null;
// 如果没有悬浮图,不需要任何交互,直接返回
if (!hasHoverImg) return;
// 如果没有悬浮图,不需要任何交互,直接返回
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选择
// 鼠标移入事件:显示悬浮图,隐藏普通图
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) {
@@ -249,15 +247,20 @@
});
}
const tabItems1 = document.querySelectorAll('.header-tab-item');
const tabContents = document.querySelectorAll('.header-tab-content');
tabItems1.forEach(tab => {
tab.addEventListener('mouseenter', () => {
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 => {
tabContents.forEach(content =>
{
content.classList.remove('active');
if (content.id === tabId) {
content.classList.add('active');
@@ -268,31 +271,33 @@
let searchHistory = JSON.parse(localStorage.getItem('searchHistory') || '[]');
function renderHistory() {
function renderHistory ()
{
const historyList = document.getElementById('historyList');
const historySection = document.getElementById('searchHistory');
if (searchHistory.length === 0) {
if (historySection) historySection.style.display = 'none';
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 => {
historySection.style.display = 'block';
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) => {
item.addEventListener('click', (e) =>
{
if (e.target === deleteBtn) return;
performSearch(keyword);
});
if (deleteBtn) {
deleteBtn.addEventListener('click', (e) => {
deleteBtn.addEventListener('click', (e) =>
{
e.stopPropagation();
const index = parseInt(deleteBtn.getAttribute('data-index'));
searchHistory.splice(index, 1);
@@ -303,7 +308,8 @@
});
}
function addToHistory(keyword) {
function addToHistory (keyword)
{
if (!keyword.trim()) return;
searchHistory = searchHistory.filter(item => item !== keyword);
searchHistory.unshift(keyword);
@@ -314,14 +320,16 @@
const clearHistoryBtn = document.getElementById('clearHistory');
if (clearHistoryBtn) {
clearHistoryBtn.addEventListener('click', () => {
clearHistoryBtn.addEventListener('click', () =>
{
searchHistory = [];
localStorage.setItem('searchHistory', JSON.stringify(searchHistory));
renderHistory();
});
}
function performSearch(keyword) {
function performSearch (keyword)
{
if (keyword.trim()) {
addToHistory(keyword);
window.location.href = "{:url('product/search')}?keywords=" + encodeURIComponent(keyword);
@@ -336,119 +344,67 @@
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) => {
if (langCloseBtn && langCloseBtn) {
langCloseBtn.addEventListener('click', (e) =>
{
e.stopPropagation();
if (langDropdown) langDropdown.classList.remove('show');
closeOverlay();
langDropdown.classList.remove('show');
});
}
//搜索关闭
if (searchCloseBtn && searchCloseBtn) {
searchCloseBtn.addEventListener('click', (e) =>
{
// 搜索关闭按钮
if (searchCloseBtn) {
searchCloseBtn.addEventListener('click', (e) => {
e.stopPropagation();
if (searchDropdown) searchDropdown.classList.remove('show');
closeOverlay();
searchDropdown.classList.remove('show');
});
}
// 鼠标移入导航项时,关闭其他弹窗
// 鼠标移入导航项时,关闭购买下拉框
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');
navItems.forEach(item =>
{
item.addEventListener('mouseenter', () =>
{
buyDropdown.classList.remove('show');
langDropdown.classList.remove('show');
searchDropdown.classList.remove('show');
});
});
// 搜索按钮点击
if (searchBtn && searchDropdown) {
searchBtn.addEventListener('click', (e) => {
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', () => {
searchSubmit.addEventListener('click', () =>
{
performSearch(searchInput.value);
});
}
if (searchInput) {
searchInput.addEventListener('keypress', (e) => {
searchInput.addEventListener('keypress', (e) =>
{
if (e.key === 'Enter') {
performSearch(searchInput.value);
}
@@ -456,44 +412,37 @@
}
const hotProducts = document.querySelectorAll('.header-hot-product-item');
hotProducts.forEach(product => {
product.addEventListener('click', () => {
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) => {
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', () => {
buyWrapper.addEventListener('click', () =>
{
// buyDropdown.classList.add('show');
buyDropdown.classList.toggle('show');
if (buyDropdown.classList.contains('show')) {
openOverlay();
} else {
closeOverlay();
}
});
}
// 全局点击关闭
document.addEventListener('click', (e) => {
document.addEventListener('click', (e) =>
{
if (!e.target.closest('.header-search-wrapper')) {
if (searchDropdown) searchDropdown.classList.remove('show');
}
@@ -503,195 +452,438 @@
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();
});
renderHistory();
// ========== 蒙版层功能(支持所有弹窗,包括导航悬停下拉) ==========
const mhk = document.getElementById('mhk');
const body = document.body;
// 获取滚动条宽度(防止打开弹窗时页面抖动)
function getScrollbarWidth() {
const scrollDiv = document.createElement('div');
scrollDiv.style.cssText = `
width: 100px;
height: 100px;
overflow: scroll;
position: absolute;
top: -9999px;
`;
document.body.appendChild(scrollDiv);
const scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth;
console.log(scrollbarWidth,'=scrollbarWidth=')
document.body.removeChild(scrollDiv);
return scrollbarWidth;
}
// 打开蒙版层的函数
function openOverlay() {
if (mhk && mhk.style.display !== 'block') {
mhk.style.display = 'block';
body.style.overflow = 'hidden';
body.style.paddingRight = getScrollbarWidth() + 'px';
}
}
// 监听弹窗状态变化关闭蒙版
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 });
}
// 关闭蒙版层的函数
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');
setupDropdownObserver(buyDropdown);
setupDropdownObserver(searchDropdown);
setupDropdownObserver(langDropdown);
// 检查导航下拉菜单是否打开(通过检查是否有 active 或显示状态)
const productDropdown = document.querySelector('.header-nav-item:first-child .header-dropdown');
const isProductDropdownOpen = productDropdown && window.getComputedStyle(productDropdown).display !== 'none';
// ========== 监听下拉菜单打开状态,自动控制蒙版 ==========
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 => {
// 检查其他导航下拉菜单
let isOtherNavOpen = false;
const otherNavItems = document.querySelectorAll('.header-nav-item:not(:first-child)');
otherNavItems.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);
});
if (dropdown && window.getComputedStyle(dropdown).display !== 'none') {
isOtherNavOpen = true;
}
});
// 只有当所有弹窗和导航下拉菜单都关闭时,才关闭蒙版层
if (!isBuyOpen && !isSearchOpen && !isLangOpen && !isProductDropdownOpen && !isOtherNavOpen) {
mhk.style.display = 'none';
body.style.overflow = '';
body.style.paddingRight = '';
}
}
// 初始化(在 DOM 加载完成后执行)
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', initHeaderDropdown);
} else {
initHeaderDropdown();
}
// 强制关闭所有弹窗和蒙版
function closeAllDropdownsAndOverlay() {
let anyOpen = false;
if (buyDropdown && buyDropdown.classList.contains('show')) {
buyDropdown.classList.remove('show');
anyOpen = true;
}
if (searchDropdown && searchDropdown.classList.contains('show')) {
searchDropdown.classList.remove('show');
anyOpen = true;
}
if (langDropdown && langDropdown.classList.contains('show')) {
langDropdown.classList.remove('show');
anyOpen = true;
}
// 关闭产品列表导航的下拉菜单通过移除hover触发的显示
const productNavItem = document.querySelector('.header-nav-item:first-child');
if (productNavItem) {
const productDropdown = productNavItem.querySelector('.header-dropdown');
if (productDropdown && window.getComputedStyle(productDropdown).display !== 'none') {
productDropdown.style.display = '';
anyOpen = true;
}
}
// 页面卸载时恢复滚动
window.addEventListener('beforeunload', () => {
if (body) {
body.style.position = '';
body.style.top = '';
body.style.left = '';
body.style.right = '';
body.style.width = '';
// 关闭其他导航的下拉菜单
const otherNavItems = document.querySelectorAll('.header-nav-item:not(:first-child)');
otherNavItems.forEach(item => {
const dropdown = item.querySelector('.header-dropdown');
if (dropdown && window.getComputedStyle(dropdown).display !== 'none') {
dropdown.style.display = '';
anyOpen = true;
}
});
// // 初始化导航下拉菜单蒙版层
// initNavDropdownOverlay();
if (anyOpen) {
closeOverlay();
} else {
closeOverlay();
}
}
// 初始化渲染
renderHistory();
closeOverlay();
// ========== 监听导航下拉菜单的显示/隐藏 ==========
// 1. 产品列表导航(第一个导航项)
const productNavItem = document.querySelector('.header-nav-item:first-child');
if (productNavItem) {
const productDropdown = productNavItem.querySelector('.header-dropdown');
// 监听鼠标进入产品列表导航
productNavItem.addEventListener('mouseenter', () => {
// 当导航下拉菜单显示时,关闭其他点击弹窗
if (searchDropdown && searchDropdown.classList.contains('show')) {
searchDropdown.classList.remove('show');
}
if (langDropdown && langDropdown.classList.contains('show')) {
langDropdown.classList.remove('show');
}
if (buyDropdown && buyDropdown.classList.contains('show')) {
buyDropdown.classList.remove('show');
}
// 打开蒙版层
openOverlay();
});
// 监听鼠标离开产品列表导航(延迟关闭,给用户移动到下拉菜单的时间)
productNavItem.addEventListener('mouseleave', () => {
setTimeout(() => {
// 检查鼠标是否在下拉菜单上
if (productDropdown) {
const isHoveringDropdown = productDropdown.matches(':hover');
const isHoveringNav = productNavItem.matches(':hover');
if (!isHoveringDropdown && !isHoveringNav) {
closeOverlay();
}
} else {
closeOverlay();
}
}, 100);
});
</script>
// 监听下拉菜单的鼠标离开事件
if (productDropdown) {
productDropdown.addEventListener('mouseleave', () => {
setTimeout(() => {
const isHoveringNav = productNavItem.matches(':hover');
if (!isHoveringNav) {
closeOverlay();
}
}, 100);
});
}
}
// 2. 其他导航项(有下拉菜单的)
const otherNavItems = document.querySelectorAll('.header-nav-item:not(:first-child)');
otherNavItems.forEach(item => {
const hasDropdown = item.querySelector('.header-dropdown');
if (hasDropdown) {
const dropdown = hasDropdown;
// 监听鼠标进入导航项
item.addEventListener('mouseenter', () => {
// 关闭其他点击弹窗
if (searchDropdown && searchDropdown.classList.contains('show')) {
searchDropdown.classList.remove('show');
}
if (langDropdown && langDropdown.classList.contains('show')) {
langDropdown.classList.remove('show');
}
if (buyDropdown && buyDropdown.classList.contains('show')) {
buyDropdown.classList.remove('show');
}
// 打开蒙版层
openOverlay();
});
// 监听鼠标离开导航项
item.addEventListener('mouseleave', () => {
setTimeout(() => {
if (dropdown) {
const isHoveringDropdown = dropdown.matches(':hover');
const isHoveringNav = item.matches(':hover');
if (!isHoveringDropdown && !isHoveringNav) {
closeOverlay();
}
} else {
closeOverlay();
}
}, 100);
});
// 监听下拉菜单的鼠标离开
if (dropdown) {
dropdown.addEventListener('mouseleave', () => {
setTimeout(() => {
const isHoveringNav = item.matches(':hover');
if (!isHoveringNav) {
closeOverlay();
}
}, 100);
});
}
}
});
// ========== 重新绑定所有点击弹窗事件 ==========
// 1. 购买弹窗
const buyWrapperNew = document.querySelector('.header-buy-wrapper');
if (buyWrapperNew && buyDropdown) {
const newBuyWrapper = buyWrapperNew.cloneNode(true);
buyWrapperNew.parentNode.replaceChild(newBuyWrapper, buyWrapperNew);
newBuyWrapper.addEventListener('click', (e) => {
e.stopPropagation();
const isOpen = buyDropdown.classList.contains('show');
if (isOpen) {
buyDropdown.classList.remove('show');
closeOverlay();
} else {
// 关闭其他弹窗和导航下拉菜单
if (searchDropdown && searchDropdown.classList.contains('show')) {
searchDropdown.classList.remove('show');
}
if (langDropdown && langDropdown.classList.contains('show')) {
langDropdown.classList.remove('show');
}
// 关闭导航下拉菜单
closeAllNavDropdowns();
buyDropdown.classList.add('show');
openOverlay();
}
});
}
// 2. 搜索弹窗
const searchBtnNew = document.querySelector('.header-search-wrapper .header-nav-btn');
if (searchBtnNew && searchDropdown) {
const newSearchBtn = searchBtnNew.cloneNode(true);
searchBtnNew.parentNode.replaceChild(newSearchBtn, searchBtnNew);
newSearchBtn.addEventListener('click', (e) => {
e.stopPropagation();
const isOpen = searchDropdown.classList.contains('show');
if (isOpen) {
searchDropdown.classList.remove('show');
closeOverlay();
} else {
// 关闭其他弹窗和导航下拉菜单
if (buyDropdown && buyDropdown.classList.contains('show')) {
buyDropdown.classList.remove('show');
}
if (langDropdown && langDropdown.classList.contains('show')) {
langDropdown.classList.remove('show');
}
// 关闭导航下拉菜单
closeAllNavDropdowns();
searchDropdown.classList.add('show');
openOverlay();
if (typeof renderHistory === 'function') {
renderHistory();
}
}
});
}
// 3. 语言弹窗
const langBtnNew = document.querySelector('.header-lang-wrapper .header-nav-btn');
if (langBtnNew && langDropdown) {
const newLangBtn = langBtnNew.cloneNode(true);
langBtnNew.parentNode.replaceChild(newLangBtn, langBtnNew);
newLangBtn.addEventListener('click', (e) => {
e.stopPropagation();
const isOpen = langDropdown.classList.contains('show');
if (isOpen) {
langDropdown.classList.remove('show');
closeOverlay();
} else {
// 关闭其他弹窗和导航下拉菜单
if (buyDropdown && buyDropdown.classList.contains('show')) {
buyDropdown.classList.remove('show');
}
if (searchDropdown && searchDropdown.classList.contains('show')) {
searchDropdown.classList.remove('show');
}
// 关闭导航下拉菜单
closeAllNavDropdowns();
langDropdown.classList.add('show');
openOverlay();
}
});
}
// 辅助函数:关闭所有导航下拉菜单
function closeAllNavDropdowns() {
// 关闭产品列表导航下拉菜单
const productNavItem = document.querySelector('.header-nav-item:first-child');
if (productNavItem) {
const productDropdown = productNavItem.querySelector('.header-dropdown');
if (productDropdown) {
productDropdown.style.display = '';
}
}
// 关闭其他导航下拉菜单
const otherNavItems = document.querySelectorAll('.header-nav-item:not(:first-child)');
otherNavItems.forEach(item => {
const dropdown = item.querySelector('.header-dropdown');
if (dropdown) {
dropdown.style.display = '';
}
});
}
// ========== 关闭按钮事件重新绑定 ==========
// 语言关闭按钮
const langCloseBtnNew = document.querySelector('.header-lang-dropdown-delete-icon');
if (langCloseBtnNew && langDropdown) {
const newLangCloseBtn = langCloseBtnNew.cloneNode(true);
langCloseBtnNew.parentNode.replaceChild(newLangCloseBtn, langCloseBtnNew);
newLangCloseBtn.addEventListener('click', (e) => {
e.stopPropagation();
langDropdown.classList.remove('show');
closeOverlay();
});
}
// 搜索关闭按钮
const searchCloseBtnNew = document.querySelector('.header-search-dropdown-delete-icon');
if (searchCloseBtnNew && searchDropdown) {
const newSearchCloseBtn = searchCloseBtnNew.cloneNode(true);
searchCloseBtnNew.parentNode.replaceChild(newSearchCloseBtn, searchCloseBtnNew);
newSearchCloseBtn.addEventListener('click', (e) => {
e.stopPropagation();
searchDropdown.classList.remove('show');
closeOverlay();
});
}
// ========== 全局点击事件 ==========
document.addEventListener('click', (e) => {
// 检查是否点击在购买区域外
if (!e.target.closest('.header-buy-wrapper') && !e.target.closest('#buyDropdown')) {
if (buyDropdown && buyDropdown.classList.contains('show')) {
buyDropdown.classList.remove('show');
closeOverlay();
}
}
// 检查是否点击在搜索区域外
if (!e.target.closest('.header-search-wrapper') && !e.target.closest('#searchDropdown')) {
if (searchDropdown && searchDropdown.classList.contains('show')) {
searchDropdown.classList.remove('show');
closeOverlay();
}
}
// 检查是否点击在语言区域外
if (!e.target.closest('.header-lang-wrapper') && !e.target.closest('#langDropdown')) {
if (langDropdown && langDropdown.classList.contains('show')) {
langDropdown.classList.remove('show');
closeOverlay();
}
}
// 检查是否点击在导航区域外(如果点击在导航外部,关闭导航下拉菜单)
if (!e.target.closest('.header-nav-item')) {
closeAllNavDropdowns();
closeOverlay();
}
});
// ========== 蒙版层点击事件 ==========
if (mhk) {
mhk.addEventListener('click', () => {
closeAllDropdownsAndOverlay();
closeAllNavDropdowns();
closeOverlay();
});
}
// ========== 监听弹窗状态变化 ==========
function setupDropdownObserver(dropdown, name) {
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, 'buy');
setupDropdownObserver(searchDropdown, 'search');
setupDropdownObserver(langDropdown, 'lang');
// ========== 页面卸载时恢复滚动 ==========
window.addEventListener('beforeunload', () => {
if (body) {
body.style.overflow = '';
body.style.paddingRight = '';
}
});
// 确保蒙版层初始状态正确
closeOverlay();
</script>

View File

@@ -4,10 +4,7 @@
box-sizing: border-box;
font-family: '微软雅黑', sans-serif;
}
html {
overflow-y: scroll;
scrollbar-gutter: stable ;
}
body {
overflow-x: hidden;
@@ -44,7 +41,7 @@ a {
.header-nav-bar {
width: 100%;
max-width: 1520px;
height:64px;
height: 4em;
display: flex;
align-items: center;
flex-wrap: nowrap;
@@ -97,11 +94,10 @@ a {
bottom: 0;
left: 0;
width: 100%;
height: 2px;
height: 0.125em;
background-color: #004bfa;
transform: scaleX(0);
transition: transform 0.2s ease;
z-index: 999;
}
.header-nav-title:hover::after,
@@ -148,7 +144,12 @@ a {
transition: color 0.2s;
}
/* .header-nav-btn img {
width: 1.5em;
max-width: 17px;
max-height: 17px;
height: 1.5em;
} */
.header-nav-btn:hover {
color: #004bfa;
@@ -255,36 +256,25 @@ a {
/* ========== 以下为原有样式,保持不变 ========== */
/* 原有的下拉框样式 - 带动画效果 */
/* 原有的下拉框样式 */
.header-dropdown {
box-sizing: border-box;
max-width: 1920px;
width: 100%;
position: absolute;
top: 64px;
top: 4em;
left: 0;
right: 0;
background-color: #fff;
z-index: 99;
z-index: 199;
border-top: none;
overflow: hidden;
padding-bottom: 2.375em;
opacity: 0;
transform: translateY(-1.25em);
pointer-events: none;
transition: opacity 0.3s ease, transform 0.3s ease;
display: none;
}
/* .header-nav-item:hover .header-dropdown {
opacity: 1;
transform: translateY(0);
pointer-events: auto;
} */
/* 添加动画锁定时的不响应状态 */
.header-dropdown.animating-out {
pointer-events: none;
.header-nav-item:hover .header-dropdown {
display: block;
}
/* Tabs切换栏居中宽度100%(基于下拉框内容区) */
@@ -335,7 +325,7 @@ a {
display: flex;
flex: 1;
justify-content: space-between;
max-width: 48%;
}
@@ -350,7 +340,10 @@ a {
}
/* 单个分类区块 */
.header-category-block {
/* flex: 1; */
}
.header-category-title {
@@ -392,14 +385,13 @@ a {
justify-content: space-between;
flex: 1;
min-width: 0;
font-size: 16px;
max-width: 748px;
}
.header-product-card {
text-align: center;
text-align: center;
width: calc(50% - 0.75em);
max-width: 22.625em;
flex-shrink: 1;
@@ -423,12 +415,12 @@ a {
transform: translateY(-2px)
}
/* .header-product-card:nth-child(1) {
} */
.header-product-card:nth-child(1) {
margin-right: 1.5em;
}
.header-product-card:nth-child(3) {
margin-right: 1.5em;
margin-top: 1.5em;
}
@@ -436,7 +428,20 @@ a {
margin-top: 1.5em;
}
/*.header-product-img {*/
/* width: 22.625em;*/
/* height: 12.25em;*/
/* background-color: #f5f5f5;*/
/* display: flex;*/
/* align-items: center;*/
/* justify-content: center;*/
/* color: #999;*/
/*}*/
/*.header-product-img img {*/
/* width: 22.625em;*/
/* height: 12.25em;*/
/*}*/
.header-product-img {
width: 100%;
aspect-ratio: 22.625 / 12.25;
@@ -446,6 +451,7 @@ a {
justify-content: center;
color: #999;
overflow: hidden;
/* border-radius: 0.5em; */
}
.header-product-img img {
@@ -946,7 +952,7 @@ a {
}
.header-dropdown-content1 {
padding: 2em 12em;
padding: 0 12em;
}
.header-buy-dropdown {
@@ -974,7 +980,7 @@ a {
}
.header-dropdown-content1 {
padding: 2em 10em;
padding: 0 10em;
}
.header-buy-dropdown {
@@ -1002,7 +1008,7 @@ a {
}
.header-dropdown-content1 {
padding: 2em 8em;
padding: 0 8em;
}
.header-buy-dropdown {
@@ -1014,7 +1020,6 @@ a {
row-gap: 60px;
}
}
/* 蒙版层样式 */
#mhk {
width: 100%;
height: 100%;
@@ -1023,7 +1028,6 @@ a {
left: 0;
backdrop-filter: blur(5px);
background-color: rgba(0, 0, 0, 0.5);
z-index: 90;
z-index: 88;
display: none;
overflow: hidden;
}