feat(layout): 重构布局组件体系与数据层

- 重构 Header 导航、Footer 页脚、MobileMenu 移动端菜单
- 新增 MobileTabBar 移动端底部导航栏
- 更新 MegaDropdown 大型下拉导航
- 重构 SEO 结构化数据组件
- 更新数据层常量 (products, services, solutions, navigation 等)
- 新增 useCountUp 数字递增 Hook
- 修复 .gitignore 中 src/lib 被错误忽略的问题
This commit is contained in:
张翔
2026-07-07 06:53:13 +08:00
parent e78df62cd1
commit 767931202d
28 changed files with 898 additions and 468 deletions
+63
View File
@@ -0,0 +1,63 @@
'use client';
import { useState, useEffect, useRef } from 'react';
interface UseCountUpOptions {
end: number;
duration?: number;
start?: number;
decimals?: number;
easing?: (t: number) => number;
enabled?: boolean;
}
const easeOutCubic = (t: number) => 1 - Math.pow(1 - t, 3);
export function useCountUp({
end,
duration = 1800,
start = 0,
decimals = 0,
easing = easeOutCubic,
enabled = true,
}: UseCountUpOptions) {
const [value, setValue] = useState(start);
const startTimeRef = useRef<number | null>(null);
const frameRef = useRef<number>(0);
useEffect(() => {
if (!enabled) {
setValue(end);
return;
}
setValue(start);
startTimeRef.current = null;
const animate = (now: number) => {
if (startTimeRef.current === null) {
startTimeRef.current = now;
}
const progress = Math.min((now - startTimeRef.current) / duration, 1);
const eased = easing(progress);
const current = start + (end - start) * eased;
setValue(Number(current.toFixed(decimals)));
if (progress < 1) {
frameRef.current = requestAnimationFrame(animate);
} else {
setValue(end);
}
};
frameRef.current = requestAnimationFrame(animate);
return () => {
cancelAnimationFrame(frameRef.current);
};
}, [end, duration, start, decimals, easing, enabled]);
return value;
}