435 lines
13 KiB
TypeScript
435 lines
13 KiB
TypeScript
'use client'
|
||
import {ReactNode, useCallback, useEffect, useMemo, useState} from 'react'
|
||
import Link from 'next/link'
|
||
import Wrap from '@/components/wrap'
|
||
|
||
export type HeaderProps = {}
|
||
|
||
export default function Header(props: HeaderProps) {
|
||
|
||
// ======================
|
||
// 滚动条状态
|
||
// ======================
|
||
|
||
const [scroll, setScroll] = useState(false) // Changed to false for client-side rendering
|
||
|
||
const handleScroll = useCallback(() => {
|
||
setScroll(window.scrollY > 48)
|
||
}, [])
|
||
|
||
useEffect(() => {
|
||
// Initialize scroll state on client
|
||
setScroll(window.scrollY > 48)
|
||
window.addEventListener('scroll', handleScroll)
|
||
return () => {
|
||
window.removeEventListener('scroll', handleScroll)
|
||
}
|
||
}, [handleScroll])
|
||
|
||
// ======================
|
||
// 菜单状态
|
||
// ======================
|
||
|
||
const [menu, setMenu] = useState(false)
|
||
const [page, setPage] = useState(0)
|
||
const pages = useMemo(() => [
|
||
<ProductMenu key={`product`}/>,
|
||
<SolutionMenu key={`solution`}/>,
|
||
<HelpMenu key={`help`}/>,
|
||
], [])
|
||
|
||
// ======================
|
||
// 覆盖状态
|
||
// ======================
|
||
|
||
const [overlay, setOverlay] = useState(false)
|
||
useEffect(() => {
|
||
setOverlay(scroll || menu)
|
||
}, [menu, scroll])
|
||
|
||
// ======================
|
||
// 渲染组件
|
||
// ======================
|
||
|
||
const LinkItem = (props: {
|
||
text: string
|
||
href: string
|
||
}) => (
|
||
<li className={`group relative`}>
|
||
<Link
|
||
href={props.href}
|
||
className={[
|
||
`h-full px-4 flex items-center text-lg`,
|
||
`transition-colors duration-200 ease-in-out`,
|
||
`hover:text-blue-500`,
|
||
].join(' ')}
|
||
>
|
||
{props.text}
|
||
</Link>
|
||
<div className={[
|
||
`absolute bottom-0 w-full h-0.5 bg-transparent `,
|
||
`transition-colors duration-200`,
|
||
`group-hover:bg-blue-500`,
|
||
].join(' ')}>
|
||
</div>
|
||
</li>
|
||
)
|
||
|
||
const MenuItem = (props: {
|
||
text: string
|
||
page: number
|
||
}) => (
|
||
<li className={`group relative`}>
|
||
<button
|
||
onPointerEnter={() => {
|
||
setMenu(true)
|
||
setPage(props.page)
|
||
}}
|
||
onPointerLeave={() => {
|
||
setMenu(false)
|
||
}}
|
||
className={[
|
||
`h-full px-4 flex gap-3 items-center cursor-pointer text-lg`,
|
||
`transition-colors duration-200 ease-in-out`,
|
||
menu && page === props.page
|
||
? `text-blue-500`
|
||
: ``,
|
||
].join(' ')}
|
||
>
|
||
<span>{props.text}</span>
|
||
<img
|
||
src={`/header/down.svg`}
|
||
alt={`drop_menu`}
|
||
className={[
|
||
`transition-transform duration-200 ease-in-out`,
|
||
menu && page === props.page
|
||
? `rotate-180`
|
||
: ``,
|
||
].join(' ')}
|
||
/>
|
||
</button>
|
||
<div className={[
|
||
`absolute bottom-0 w-full h-0.5 bg-transparent pointer-events-none`,
|
||
`transition-colors duration-200`,
|
||
menu && page === props.page ? `bg-blue-500` : '',
|
||
].join(' ')}>
|
||
</div>
|
||
</li>
|
||
|
||
)
|
||
|
||
return (
|
||
<header className={[
|
||
`fixed top-0 w-full z-10`,
|
||
].join(' ')}>
|
||
<div className={[
|
||
``,
|
||
`transition-[background, shadow] duration-200 ease-in-out`,
|
||
menu
|
||
? `bg-[#fffe] backdrop-blur-sm`
|
||
: scroll
|
||
? `bg-[#fffe] backdrop-blur-sm shadow-lg`
|
||
: `bg-transparent shadow-none`,
|
||
].join(' ')}>
|
||
<Wrap className="h-20 max-md:h-16 flex justify-between">
|
||
<div className="flex justify-between gap-8">
|
||
{/* logo */}
|
||
<Link href="/public" className={`flex items-center`}>
|
||
<img src={`/logo.svg`} alt={`logo`} className={`w-16 max-md:w-12 h-16 max-md:h-12 rounded-full bg-gray-100`}/>
|
||
</Link>
|
||
|
||
{/* 菜单 */}
|
||
<nav>
|
||
<ul className="h-full flex items-stretch max-lg:hidden">
|
||
<LinkItem text={`首页`} href={`/`}/>
|
||
<MenuItem text={`产品订购`} page={0}/>
|
||
<MenuItem text={`业务场景`} page={1}/>
|
||
<MenuItem text={`帮助中心`} page={2}/>
|
||
<LinkItem text={`企业服务`} href={`#`}/>
|
||
<LinkItem text={`推广返利`} href={`#`}/>
|
||
</ul>
|
||
</nav>
|
||
</div>
|
||
{/* 登录 */}
|
||
<div className={`flex items-center`}>
|
||
<a
|
||
href="#"
|
||
className={`w-24 h-12 flex items-center justify-center lg:text-lg font-medium`}
|
||
>
|
||
<span>登录</span>
|
||
</a>
|
||
<a
|
||
href="#"
|
||
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`}
|
||
>
|
||
<span>注册</span>
|
||
</a>
|
||
</div>
|
||
</Wrap>
|
||
</div>
|
||
|
||
{/* 下拉菜单 */}
|
||
<div
|
||
className={[
|
||
`shadow-lg`,
|
||
`overflow-hidden bg-[#fffe] backdrop-blur-sm`,
|
||
`transition-[opacity,padding,height] transition-discrete duration-200 ease-in-out`,
|
||
menu
|
||
? `delay-[0s,0s,0s] opacity-100 py-8 h-auto`
|
||
: `delay-[0s,0s,0.2s] opacity-0 py-0 h-0`,
|
||
].join(' ')}
|
||
onPointerEnter={() => setMenu(true)}
|
||
onPointerLeave={() => setMenu(false)}
|
||
>
|
||
{pages[page]}
|
||
</div>
|
||
</header>
|
||
)
|
||
}
|
||
|
||
function ProductMenu() {
|
||
|
||
// ====================
|
||
// Tab 选项
|
||
// ====================
|
||
|
||
type TabType = 'domestic' | 'oversea'
|
||
const [type, setType] = useState<TabType>('domestic')
|
||
|
||
const Tab = (props: {
|
||
type: TabType,
|
||
children: ReactNode
|
||
}) => {
|
||
return (
|
||
<li role="tab">
|
||
<button
|
||
className={[
|
||
`p-8 text-lg cursor-pointer border-r`,
|
||
type === props.type ? `bg-gradient-to-r from-transparent to-blue-200 border-blue-400` : `border-gray-200`,
|
||
].join(' ')}
|
||
onClick={() => setType(props.type)}
|
||
>
|
||
{props.children}
|
||
</button>
|
||
</li>
|
||
)
|
||
}
|
||
|
||
// ====================
|
||
// 渲染组件
|
||
// ====================
|
||
|
||
return (
|
||
<Wrap className="flex">
|
||
<ul role="tablist" className="w-48">
|
||
<Tab type="domestic">国内代理</Tab>
|
||
<Tab type="oversea">海外代理</Tab>
|
||
</ul>
|
||
<div className="flex-1">
|
||
{type === 'domestic'
|
||
? (
|
||
<section role="tabpanel" className="flex gap-16 mr-16">
|
||
<div className="w-64 flex flex-col gap-6">
|
||
<h3 className="font-bold mb-2 flex items-center gap-3">
|
||
<img src={`/prod.svg`} alt={`产品`} className={`w-10 h-=10`}/>
|
||
<span>代理产品</span>
|
||
</h3>
|
||
<div className="flex flex-col gap-2">
|
||
<p className="flex gap-2">
|
||
<span>短效动态IP</span>
|
||
<span className="text-orange-500 text-xs text-light px-2 py-1 bg-orange-50 rounded-full">
|
||
折扣45%
|
||
</span>
|
||
</p>
|
||
<p className="text-gray-400 text-sm">
|
||
全国300+城市级定位节点
|
||
</p>
|
||
</div>
|
||
<div className="flex flex-col gap-2">
|
||
<p className="flex gap-2">
|
||
<span>长效静态IP</span>
|
||
<span className="text-orange-500 text-xs text-light px-2 py-1 bg-orange-50 rounded-full">
|
||
折扣45%
|
||
</span>
|
||
</p>
|
||
<p className="text-gray-400 text-sm">
|
||
IPI资源覆盖全国
|
||
</p>
|
||
</div>
|
||
<div>
|
||
<p className="flex gap-2">
|
||
<span>固定IP</span>
|
||
<span className="text-orange-500 text-xs text-light px-2 py-1 bg-orange-50 rounded-full">
|
||
折扣45%
|
||
</span>
|
||
</p>
|
||
</div>
|
||
</div>
|
||
<div className="w-64 flex flex-col gap-4">
|
||
<h3 className="font-bold mb-2 flex items-center gap-3">
|
||
<img src="/custom.svg" alt="定制" className="w-10 h-10"/>
|
||
<span>业务定制</span>
|
||
</h3>
|
||
<div className="flex flex-col gap-2">
|
||
<p>优质/企业/精选IP</p>
|
||
<p className="text-gray-400 text-sm">
|
||
超 1000 家企业共同信赖之选!大客户经理全
|
||
程 1 对 1 沟通,随时为您排忧解难,提供 24
|
||
小时不间断支持
|
||
</p>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
) : (
|
||
<section role="tabpanel">
|
||
|
||
</section>
|
||
)
|
||
}
|
||
</div>
|
||
<aside className="w-64">
|
||
<h3 className="flex gap-3 items-center mb-4">
|
||
<img src={`/anno.svg`} alt={`公告`} className={`w-10 h-10`}/>
|
||
<span>网站公告</span>
|
||
</h3>
|
||
<div className="flex flex-col gap-2">
|
||
<p>官网最新上线,体验再升级!</p>
|
||
<p className="text-gray-400 text-sm">
|
||
1.新增多样使用功能,新增多样使用
|
||
新增多样使用功能
|
||
</p>
|
||
<p className="text-gray-400 text-sm">
|
||
2.新增多样使用功能,新增多样使用
|
||
新增多样使用功能
|
||
</p>
|
||
</div>
|
||
</aside>
|
||
</Wrap>
|
||
)
|
||
}
|
||
|
||
function SolutionMenu() {
|
||
|
||
const SolutionItem = (props: {
|
||
icon: string
|
||
title: string
|
||
desc: string
|
||
}) => {
|
||
return (
|
||
<div
|
||
className={[
|
||
`h-full p-4 flex gap-4 items-start rounded-md cursor-pointer`,
|
||
`transition-colors duration-200 hover:bg-blue-100`,
|
||
].join(' ')}
|
||
>
|
||
<img src={`/header/solution/${props.icon}.svg`} alt={props.title} className="w-10 h-10"/>
|
||
<div className="flex flex-col gap-1">
|
||
<h3 className="font-bold">{props.title}</h3>
|
||
<p className="text-gray-400 text-sm">{props.desc}</p>
|
||
</div>
|
||
</div>
|
||
)
|
||
}
|
||
|
||
return (
|
||
<Wrap className="grid grid-cols-4 auto-rows-fr gap-4">
|
||
<SolutionItem
|
||
icon="01"
|
||
title="数据抓取"
|
||
desc="高效采集和分析大量数据,助力企业获取大量情报"
|
||
/>
|
||
<SolutionItem
|
||
icon="02"
|
||
title="广告验证"
|
||
desc="确保广告点击和展示数据的真实性,帮助企业,提升广告效果"
|
||
/>
|
||
<SolutionItem
|
||
icon="03"
|
||
title="市场调查"
|
||
desc="收集全网行业数据,了解竞争对手动态"
|
||
/>
|
||
<SolutionItem
|
||
icon="04"
|
||
title="SEO优化"
|
||
desc="收集搜索引擎情报,提高网站在搜索引擎的排名"
|
||
/>
|
||
<SolutionItem
|
||
icon="05"
|
||
title="品牌保护"
|
||
desc="保护品牌商标打造,优质品牌形象,为企业获得更多用户"
|
||
/>
|
||
<SolutionItem
|
||
icon="06"
|
||
title="价格监控"
|
||
desc="利用优质代理IP,实时监控行业价格信息,提高市场竞争力"
|
||
/>
|
||
<SolutionItem
|
||
icon="07"
|
||
title="金融数据"
|
||
desc="快速获取金融市场实时数据,帮助投资者分析趋势,使其做出精准决策"
|
||
/>
|
||
<SolutionItem
|
||
icon="08"
|
||
title="网站测试"
|
||
desc="在不同环境下对网站进行性能和兼容的测试,让用户有高质量体验"
|
||
/>
|
||
</Wrap>
|
||
)
|
||
}
|
||
|
||
function HelpMenu() {
|
||
|
||
const Column = (props: {
|
||
icon: string,
|
||
title: string,
|
||
items: {
|
||
lead: string
|
||
href: string
|
||
}[]
|
||
}) => (
|
||
<div className="flex flex-col gap-4">
|
||
<h3 className="font-bold flex gap-3 items-center">
|
||
<img src={`/header/help/${props.icon}.svg`} alt={props.title} className="w-10 h-10"/>
|
||
<span>{props.title}</span>
|
||
</h3>
|
||
<ul className=" text-gray-500 text-sm flex flex-col items-end gap-2">
|
||
{props.items.map((item, index) => (
|
||
<li key={index}><Link href={item.href}>{item.lead}</Link></li>
|
||
))}
|
||
</ul>
|
||
</div>
|
||
)
|
||
|
||
return (
|
||
<Wrap className="w-full grid grid-cols-4 gap-4 justify-items-center">
|
||
<Column
|
||
icon="01"
|
||
title="提取IP"
|
||
items={[
|
||
{lead: '短效动态IP提取', href: '#'},
|
||
{lead: '长效静态IP提取', href: '#'},
|
||
]}
|
||
/>
|
||
<Column
|
||
icon="02"
|
||
title="使用教程"
|
||
items={[
|
||
{lead: '快速入手', href: '#'},
|
||
{lead: '代码下载', href: '#'},
|
||
{lead: 'API文档', href: '#'},
|
||
]}
|
||
/>
|
||
<Column
|
||
icon="03"
|
||
title="产品功能"
|
||
items={[
|
||
{lead: '常见问题', href: '#'},
|
||
{lead: '产品介绍', href: '#'},
|
||
{lead: '行业资讯', href: '#'},
|
||
]}
|
||
/>
|
||
<img src={`/header/help/banner.webp`} alt={`banner`} className={``}/>
|
||
</Wrap>
|
||
)
|
||
}
|