feat: 统一全站设计风格、导航组件与文案逻辑自洽性修复
- 新增 InkGlowCard 墨韵流光卡片组件,统一全站卡片交互风格 - 新增 PageNav 面包屑组件,统一全站页面导航 - 统一色彩体系、排版层级、间距节奏和动画风格 - 修复 CTA 区品牌名称错误(诺瓦隆→睿新致遠) - 修复 ERP 产品卖点与年费制定价矛盾 - 导航下拉补充 SDS 和 OA 产品 - 统一全站数据指标为 12+年核心团队经验、6自研产品、10+团队成员 - 移除不可靠的 100%客户满意度和 30+行业专家指标 - 修复新闻时间线不合理问题,调整里程碑节奏 - 统一响应承诺为工作日快速响应 - 服务第4项重命名为行业方案实施,厘清概念 - 服务详情页效果数据改为定性描述 - 删除 cases 模块,精简代码库
This commit is contained in:
@@ -1,9 +1,9 @@
|
||||
'use client';
|
||||
|
||||
import { Suspense, useState, useEffect, useCallback, useRef } from 'react';
|
||||
import { Suspense, useState, useEffect, useCallback } from 'react';
|
||||
import { StaticLink } from '@/components/ui/static-link';
|
||||
import Image from 'next/image';
|
||||
import { usePathname, useSearchParams } from 'next/navigation';
|
||||
import { usePathname } from 'next/navigation';
|
||||
import { Menu, X } from 'lucide-react';
|
||||
import { AnimatePresence, motion } from 'framer-motion';
|
||||
import { Button } from '@/components/ui/button';
|
||||
@@ -11,58 +11,16 @@ import { COMPANY_INFO, NAVIGATION_V2, MEGA_DROPDOWN_DATA, type NavigationItemV2
|
||||
import { MegaDropdown } from '@/components/layout/mega-dropdown';
|
||||
import { useFocusTrap } from '@/hooks/use-focus-trap';
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
__isProgrammaticScroll?: boolean;
|
||||
}
|
||||
}
|
||||
|
||||
function HeaderContent() {
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const [isScrolled, setIsScrolled] = useState(false);
|
||||
const [openDropdown, setOpenDropdown] = useState<string | null>(null);
|
||||
const pathname = usePathname();
|
||||
const searchParams = useSearchParams();
|
||||
const focusTrapRef = useFocusTrap<HTMLDivElement>(isOpen);
|
||||
const isScrollingRef = useRef(false);
|
||||
const scrollTimeoutRef = useRef<NodeJS.Timeout | null>(null);
|
||||
|
||||
const getActiveSection = useCallback(() => {
|
||||
if (pathname === '/contact') {return 'contact';}
|
||||
if (pathname === '/') {
|
||||
const section = searchParams.get('section');
|
||||
return section || 'home';
|
||||
}
|
||||
return '';
|
||||
}, [pathname, searchParams]);
|
||||
|
||||
const activeSection = getActiveSection();
|
||||
|
||||
useEffect(() => {
|
||||
const handleScroll = () => {
|
||||
setIsScrolled(window.scrollY > 20);
|
||||
|
||||
if (pathname === '/' && !isScrollingRef.current && !window.__isProgrammaticScroll) {
|
||||
const scrollPosition = window.scrollY + 100;
|
||||
const sections = ['home', 'services', 'solutions', 'products', 'cases', 'about', 'team', 'news'];
|
||||
|
||||
for (const sectionId of sections) {
|
||||
const element = document.getElementById(sectionId);
|
||||
if (element) {
|
||||
const offsetTop = element.offsetTop;
|
||||
const offsetHeight = element.offsetHeight;
|
||||
|
||||
if (scrollPosition >= offsetTop && scrollPosition < offsetTop + offsetHeight) {
|
||||
const currentSection = searchParams.get('section') || 'home';
|
||||
if (currentSection !== sectionId) {
|
||||
const url = sectionId === 'home' ? '/' : `/?section=${sectionId}`;
|
||||
window.history.replaceState(null, '', url);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const handleGlobalKeyDown = (e: KeyboardEvent) => {
|
||||
@@ -77,11 +35,8 @@ function HeaderContent() {
|
||||
return () => {
|
||||
window.removeEventListener('scroll', handleScroll);
|
||||
window.removeEventListener('keydown', handleGlobalKeyDown);
|
||||
if (scrollTimeoutRef.current) {
|
||||
clearTimeout(scrollTimeoutRef.current);
|
||||
}
|
||||
};
|
||||
}, [pathname, isOpen, searchParams]);
|
||||
}, [isOpen]);
|
||||
|
||||
const handleKeyDown = useCallback((e: React.KeyboardEvent) => {
|
||||
if (e.key === 'Enter' || e.key === ' ') {
|
||||
@@ -95,57 +50,25 @@ function HeaderContent() {
|
||||
|
||||
const handleNavClick = useCallback((e: React.MouseEvent<HTMLAnchorElement>, item: NavigationItemV2) => {
|
||||
e.preventDefault();
|
||||
|
||||
if (item.id === 'contact') {
|
||||
window.location.href = '/contact';
|
||||
} else if (item.id === 'home') {
|
||||
if (pathname === '/') {
|
||||
isScrollingRef.current = true;
|
||||
window.scrollTo({ top: 0, behavior: 'smooth' });
|
||||
window.history.pushState(null, '', '/');
|
||||
|
||||
scrollTimeoutRef.current = setTimeout(() => {
|
||||
isScrollingRef.current = false;
|
||||
}, 1000);
|
||||
} else {
|
||||
window.location.href = '/';
|
||||
}
|
||||
} else {
|
||||
if (pathname === '/') {
|
||||
const scrollToSection = (retryCount = 0) => {
|
||||
const element = document.getElementById(item.id);
|
||||
if (element) {
|
||||
isScrollingRef.current = true;
|
||||
element.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
||||
window.history.pushState(null, '', `/?section=${item.id}`);
|
||||
|
||||
scrollTimeoutRef.current = setTimeout(() => {
|
||||
isScrollingRef.current = false;
|
||||
}, 1000);
|
||||
} else if (retryCount < 10) {
|
||||
setTimeout(() => scrollToSection(retryCount + 1), 100);
|
||||
}
|
||||
};
|
||||
scrollToSection();
|
||||
} else {
|
||||
window.location.href = `/?section=${item.id}`;
|
||||
}
|
||||
}
|
||||
|
||||
window.location.href = item.href;
|
||||
setIsOpen(false);
|
||||
}, [pathname]);
|
||||
}, []);
|
||||
|
||||
const isActive = useCallback((item: NavigationItemV2) => {
|
||||
if (item.id === 'contact') {
|
||||
return pathname === '/contact';
|
||||
}
|
||||
|
||||
if (pathname === '/') {
|
||||
return activeSection === item.id;
|
||||
if (item.id === 'home') {
|
||||
return pathname === '/';
|
||||
}
|
||||
|
||||
return false;
|
||||
}, [pathname, activeSection]);
|
||||
if (item.id === 'products') {
|
||||
return pathname === '/products' || pathname.startsWith('/products/');
|
||||
}
|
||||
if (item.id === 'solutions') {
|
||||
return pathname === '/solutions' || pathname.startsWith('/solutions/');
|
||||
}
|
||||
return pathname === `/${item.id}`;
|
||||
}, [pathname]);
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -169,9 +92,9 @@ function HeaderContent() {
|
||||
<Image
|
||||
src="/logo.svg"
|
||||
alt={COMPANY_INFO.name}
|
||||
width={128}
|
||||
height={32}
|
||||
className="transition-transform duration-200 group-hover:scale-105"
|
||||
width={120}
|
||||
height={30}
|
||||
className="transition-transform duration-200 group-hover:scale-105 w-auto h-8 md:h-8"
|
||||
loading="eager"
|
||||
priority
|
||||
/>
|
||||
|
||||
Reference in New Issue
Block a user