2025-03-11 14:57:23 +08:00
|
|
|
'use client'
|
2025-03-12 15:13:37 +08:00
|
|
|
import {ReactNode, useCallback, useEffect, useMemo, useState} from 'react'
|
2025-03-11 14:57:23 +08:00
|
|
|
import Link from 'next/link'
|
|
|
|
|
import Wrap from '@/components/wrap'
|
|
|
|
|
|
|
|
|
|
export type HeaderProps = {}
|
|
|
|
|
|
|
|
|
|
export default function Header(props: HeaderProps) {
|
|
|
|
|
|
2025-03-12 15:13:37 +08:00
|
|
|
// ======================
|
|
|
|
|
// 滚动条状态
|
|
|
|
|
// ======================
|
2025-03-11 14:57:23 +08:00
|
|
|
|
2025-03-12 15:13:37 +08:00
|
|
|
const [scroll, setScroll] = useState(window.scrollY > 48)
|
|
|
|
|
|
|
|
|
|
const handleScroll = useCallback(() => {
|
|
|
|
|
setScroll(window.scrollY > 48)
|
|
|
|
|
}, [])
|
2025-03-11 14:57:23 +08:00
|
|
|
useEffect(() => {
|
|
|
|
|
window.addEventListener('scroll', handleScroll)
|
|
|
|
|
return () => {
|
|
|
|
|
window.removeEventListener('scroll', handleScroll)
|
|
|
|
|
}
|
2025-03-12 15:13:37 +08:00
|
|
|
}, [handleScroll])
|
|
|
|
|
|
|
|
|
|
// ======================
|
|
|
|
|
// 菜单状态
|
|
|
|
|
// ======================
|
|
|
|
|
|
|
|
|
|
const [menu, setMenu] = useState<string>('')
|
|
|
|
|
|
|
|
|
|
// ======================
|
|
|
|
|
// 覆盖状态
|
|
|
|
|
// ======================
|
|
|
|
|
|
|
|
|
|
const [overlay, setOverlay] = useState(false)
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
setOverlay(scroll || menu !== '')
|
|
|
|
|
}, [menu, scroll])
|
|
|
|
|
|
|
|
|
|
// ======================
|
|
|
|
|
// 渲染组件
|
|
|
|
|
// ======================
|
2025-03-11 14:57:23 +08:00
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<header
|
|
|
|
|
className={[
|
2025-03-12 15:13:37 +08:00
|
|
|
`fixed top-0 w-full`,
|
|
|
|
|
`transition-all duration-200 ${overlay ? `bg-[#fffe] shadow-lg backdrop-blur-sm` : 'bg-transparent shadow-transparent'}`,
|
2025-03-11 14:57:23 +08:00
|
|
|
].join(' ')}>
|
2025-03-12 15:13:37 +08:00
|
|
|
<Wrap className=" h-20 max-md:h-16 flex justify-between">
|
|
|
|
|
<div className="flex justify-between gap-8">
|
2025-03-11 14:57:23 +08:00
|
|
|
{/* logo */}
|
2025-03-12 15:13:37 +08:00
|
|
|
<Link href="/" className={`flex items-center`}>
|
2025-03-12 11:11:54 +08:00
|
|
|
<img src={`/logo.svg`} alt={`logo`} className={`w-16 max-md:w-12 h-16 max-md:h-12 rounded-full bg-gray-100`}/>
|
2025-03-11 14:57:23 +08:00
|
|
|
</Link>
|
|
|
|
|
|
|
|
|
|
{/* 菜单 */}
|
2025-03-12 15:13:37 +08:00
|
|
|
<nav>
|
|
|
|
|
<ul className="h-full flex items-center text-xl max-lg:hidden">
|
2025-03-11 14:57:23 +08:00
|
|
|
<NavItemTop>
|
|
|
|
|
<Link href={`/`}>首页</Link>
|
|
|
|
|
</NavItemTop>
|
2025-03-12 15:13:37 +08:00
|
|
|
|
|
|
|
|
<NavItemTop
|
|
|
|
|
onEnter={() => setMenu('product')}
|
|
|
|
|
onLeave={() => setMenu('')}
|
|
|
|
|
>
|
|
|
|
|
<button className={`cursor-pointer`}>产品订购</button>
|
2025-03-11 14:57:23 +08:00
|
|
|
<SvgDown/>
|
|
|
|
|
</NavItemTop>
|
2025-03-12 15:13:37 +08:00
|
|
|
|
|
|
|
|
<NavItemTop
|
|
|
|
|
onEnter={() => setMenu('solution')}
|
|
|
|
|
onLeave={() => setMenu('')}
|
|
|
|
|
>
|
|
|
|
|
<button className={`cursor-pointer`}>业务场景</button>
|
2025-03-11 14:57:23 +08:00
|
|
|
<SvgDown/>
|
|
|
|
|
</NavItemTop>
|
2025-03-12 15:13:37 +08:00
|
|
|
|
|
|
|
|
<NavItemTop
|
|
|
|
|
onEnter={() => setMenu('help')}
|
|
|
|
|
onLeave={() => setMenu('')}
|
|
|
|
|
>
|
|
|
|
|
<button className={`cursor-pointer`}>帮助中心</button>
|
2025-03-11 14:57:23 +08:00
|
|
|
<SvgDown/>
|
|
|
|
|
</NavItemTop>
|
2025-03-12 15:13:37 +08:00
|
|
|
|
2025-03-11 14:57:23 +08:00
|
|
|
<NavItemTop>
|
|
|
|
|
<Link href={`#`}>企业服务</Link>
|
|
|
|
|
</NavItemTop>
|
2025-03-12 15:13:37 +08:00
|
|
|
|
2025-03-11 14:57:23 +08:00
|
|
|
<NavItemTop>
|
|
|
|
|
<Link href={`#`}>推广返利</Link>
|
|
|
|
|
</NavItemTop>
|
|
|
|
|
</ul>
|
|
|
|
|
</nav>
|
|
|
|
|
</div>
|
|
|
|
|
{/* 登录 */}
|
|
|
|
|
<div className={`flex items-center`}>
|
|
|
|
|
<a
|
|
|
|
|
href="#"
|
2025-03-12 11:11:54 +08:00
|
|
|
className={`w-24 h-12 flex items-center justify-center lg:text-lg font-medium`}>
|
2025-03-11 14:57:23 +08:00
|
|
|
<span>登录</span>
|
|
|
|
|
</a>
|
|
|
|
|
<a
|
|
|
|
|
href="#"
|
2025-03-12 11:11:54 +08:00
|
|
|
className={`w-20 lg:w-24 h-10 lg:h-12 bg-gradient-to-r from-blue-500 to-cyan-400 rounded-sm flex items-center justify-center lg:text-lg font-medium text-white`}>
|
2025-03-11 14:57:23 +08:00
|
|
|
<span>注册</span>
|
|
|
|
|
</a>
|
|
|
|
|
</div>
|
|
|
|
|
</Wrap>
|
2025-03-12 15:13:37 +08:00
|
|
|
|
|
|
|
|
{/* 下拉菜单 */}
|
|
|
|
|
<div
|
|
|
|
|
className={[
|
|
|
|
|
`transition-[visibility,opacity,height] duration-200 ease-in-out`,
|
|
|
|
|
`${menu === ''
|
|
|
|
|
? 'delay-[200ms,0s,0s] invisible opacity-0 h-0 pointer-events-none'
|
|
|
|
|
: 'delay-[0s,0s,0s] visible opacity-100 h-80'
|
|
|
|
|
}`,
|
|
|
|
|
].join(' ')}>
|
|
|
|
|
</div>
|
|
|
|
|
{{
|
|
|
|
|
'product': <ProductMenu/>,
|
|
|
|
|
'solution': <SolutionMenu/>,
|
|
|
|
|
'help': <HelpMenu/>,
|
|
|
|
|
}[menu]}
|
|
|
|
|
Using a wrapper div to handle transitions
|
2025-03-11 14:57:23 +08:00
|
|
|
</header>
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
2025-03-12 15:13:37 +08:00
|
|
|
function NavItemTop(props: {
|
2025-03-11 14:57:23 +08:00
|
|
|
children: ReactNode
|
2025-03-12 15:13:37 +08:00
|
|
|
onEnter?: () => void
|
|
|
|
|
onLeave?: () => void
|
|
|
|
|
}) {
|
2025-03-11 14:57:23 +08:00
|
|
|
return (
|
2025-03-12 15:13:37 +08:00
|
|
|
<li className={`h-10 px-4 flex items-center text-xl cursor-pointer`} onPointerEnter={props.onEnter} onPointerLeave={props.onLeave}>
|
2025-03-11 14:57:23 +08:00
|
|
|
{props.children}
|
|
|
|
|
</li>
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function SvgDown() {
|
|
|
|
|
return (
|
|
|
|
|
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
|
|
|
<path
|
|
|
|
|
d="M6 9L12 15L18 9" stroke="currentColor" strokeWidth="2" strokeLinecap="round"
|
|
|
|
|
strokeLinejoin="round"/>
|
|
|
|
|
</svg>
|
|
|
|
|
)
|
|
|
|
|
}
|
2025-03-12 15:13:37 +08:00
|
|
|
|
|
|
|
|
function ProductMenu() {
|
|
|
|
|
const [type, setType] = useState<'domestic' | 'oversea'>('domestic')
|
|
|
|
|
return (
|
|
|
|
|
<div className={`flex`}>
|
|
|
|
|
<ul role={`tablist`}>
|
|
|
|
|
<li role={`tab`}>
|
|
|
|
|
<button onClick={() => setType('domestic')}>
|
|
|
|
|
国内代理
|
|
|
|
|
</button>
|
|
|
|
|
</li>
|
|
|
|
|
<li role={`tab`}>
|
|
|
|
|
<button onClick={() => setType('oversea')}>
|
|
|
|
|
海外代理
|
|
|
|
|
</button>
|
|
|
|
|
</li>
|
|
|
|
|
</ul>
|
|
|
|
|
<section role={`tabpanel`}>
|
|
|
|
|
{{
|
|
|
|
|
'domestic': <div>国内代理</div>,
|
|
|
|
|
'oversea': <div>海外代理</div>,
|
|
|
|
|
}[type]}
|
|
|
|
|
</section>
|
|
|
|
|
</div>
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function SolutionMenu() {
|
|
|
|
|
return (
|
|
|
|
|
<div>解决方案</div>
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function HelpMenu() {
|
|
|
|
|
return (
|
|
|
|
|
<div>帮助中心</div>
|
|
|
|
|
)
|
|
|
|
|
}
|