优化页头样式与操控 & 优化首页推荐文章部分 & 修复后台未正确流式加载问题
This commit is contained in:
12
README.md
12
README.md
@@ -1,23 +1,17 @@
|
||||
## TODO
|
||||
|
||||
长效动态统计
|
||||
|
||||
页头产品订购 - 网站公告
|
||||
|
||||
页尾服务保障跳转企业微信
|
||||
|
||||
首页推荐文章
|
||||
提取记录,长效动态统计
|
||||
|
||||
购买页固定套餐
|
||||
|
||||
价格展示原价和折扣价
|
||||
|
||||
### 禁止直接依赖 form
|
||||
|
||||
`\[(.*,)?form(,.*)?\]`
|
||||
|
||||
### 次要
|
||||
|
||||
页头高度降低
|
||||
|
||||
帮助中心文档优化
|
||||
|
||||
考虑重新组织导航栏
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
'use client'
|
||||
import {ReactNode, useContext, useState} from 'react'
|
||||
import Wrap from '@/components/wrap'
|
||||
import anno from '@/assets/header/product/anno.svg'
|
||||
import Link from 'next/link'
|
||||
import {merge} from '@/lib/utils'
|
||||
import prod from '@/assets/header/product/prod.svg'
|
||||
@@ -27,20 +26,7 @@ export default function ProductMenu() {
|
||||
<Oversea/>
|
||||
)
|
||||
}
|
||||
<aside className="w-full lg:w-64 hidden lg:block">
|
||||
<FragmentTitle img={anno} text="网站公告"/>
|
||||
<div className="flex flex-col gap-2 p-4">
|
||||
<p>官网最新上线,体验再升级!</p>
|
||||
<p className="text-gray-400 text-sm">
|
||||
1.新增多样使用功能,新增多样使用
|
||||
新增多样使用功能
|
||||
</p>
|
||||
<p className="text-gray-400 text-sm">
|
||||
2.新增多样使用功能,新增多样使用
|
||||
新增多样使用功能
|
||||
</p>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
</Wrap>
|
||||
)
|
||||
}
|
||||
@@ -69,27 +55,24 @@ export function Domestic(props: {}) {
|
||||
return (
|
||||
<section role="tabpanel" className="flex-auto flex flex-col lg:flex-row justify-evenly gap-3 lg:gap-0">
|
||||
<div className="w-full lg:w-64 flex flex-col">
|
||||
<FragmentTitle img={prod} text="代理产品"/>
|
||||
<FragmentTitle img={prod} text="短效 IP"/>
|
||||
<DomesticLink
|
||||
label="短效动态 IP"
|
||||
desc="全国300+城市级定位节点"
|
||||
desc="全国 300+ 城市级定位节点,IP 池资源充足,自动高频切换。适用于数据采集、市场调研、SEO 优化等高并发场景。稳定可靠,响应迅速,助力业务高效运转。"
|
||||
href="/product?type=short"
|
||||
discount={45}
|
||||
/>
|
||||
</div>
|
||||
<div className="w-full lg:w-64 flex flex-col">
|
||||
<FragmentTitle img={prod} text="长效 IP"/>
|
||||
<DomesticLink
|
||||
label="长效动态 IP"
|
||||
desc="IP 资源覆盖全国"
|
||||
desc="IP 存活时长可达数小时至数天,连接稳定不掉线。适用于账号养号、社交运营、电商管理等需要持续在线的场景。优质线路保障,为您的长期业务保驾护航。"
|
||||
href="/product?type=long"
|
||||
discount={45}
|
||||
/>
|
||||
<DomesticLink
|
||||
label="静态 IP"
|
||||
desc="全国300+城市级定位节点"
|
||||
href="/product?type=fixed"
|
||||
discount={45}
|
||||
/>
|
||||
</div>
|
||||
<div className="w-full lg:w-64 flex flex-col lg:max-lg:hidden">
|
||||
<div className="w-full lg:w-64 flex flex-col">
|
||||
<FragmentTitle img={custom} text="业务定制"/>
|
||||
<DomesticLink
|
||||
label="优质/企业/精选IP"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
'use client'
|
||||
import {useMemo, useState, PointerEvent, ComponentProps, useSyncExternalStore, use, Suspense} from 'react'
|
||||
import {useMemo, useState, PointerEvent, ComponentProps, useSyncExternalStore, use, Suspense, MouseEvent} from 'react'
|
||||
import Link from 'next/link'
|
||||
import Image from 'next/image'
|
||||
import {HeaderContext} from './_components/header/common'
|
||||
@@ -43,10 +43,20 @@ export default function Header(props: HeaderProps) {
|
||||
<MobileMenu key="mobile"/>,
|
||||
], [])
|
||||
|
||||
const toggleMobileMenu = () => {
|
||||
if (menu) {
|
||||
setMenu(false)
|
||||
}
|
||||
else {
|
||||
setPage(3)
|
||||
setMenu(true)
|
||||
}
|
||||
}
|
||||
|
||||
const enterMenu = (i: number) => {
|
||||
return (e: PointerEvent) => {
|
||||
setPage(i)
|
||||
if (e.pointerType === 'mouse' || page !== i) {
|
||||
if (page !== i) {
|
||||
setMenu(true)
|
||||
}
|
||||
else {
|
||||
@@ -55,18 +65,16 @@ export default function Header(props: HeaderProps) {
|
||||
}
|
||||
}
|
||||
|
||||
const exitMenu = (e: PointerEvent) => {
|
||||
if (e.pointerType === 'mouse') {
|
||||
setMenu(false)
|
||||
}
|
||||
const leaveMenu = (e: PointerEvent) => {
|
||||
setMenu(false)
|
||||
}
|
||||
|
||||
const enterMenuContent = (e: PointerEvent) => {
|
||||
setMenu(true)
|
||||
}
|
||||
|
||||
const exitMenuContent = (e: PointerEvent) => {
|
||||
if (e.pointerType === 'mouse') {
|
||||
const leaveMenuContent = (e: PointerEvent) => {
|
||||
if (page != 3) {
|
||||
setMenu(false)
|
||||
}
|
||||
}
|
||||
@@ -115,19 +123,19 @@ export default function Header(props: HeaderProps) {
|
||||
text="产品订购"
|
||||
active={menu && page === 0}
|
||||
onPointerEnter={enterMenu(0)}
|
||||
onPointerLeave={exitMenu}
|
||||
onPointerLeave={leaveMenu}
|
||||
/>
|
||||
<MenuItem
|
||||
text="业务场景"
|
||||
active={menu && page === 1}
|
||||
onPointerEnter={enterMenu(1)}
|
||||
onPointerLeave={exitMenu}
|
||||
onPointerLeave={leaveMenu}
|
||||
/>
|
||||
<MenuItem
|
||||
text="帮助中心"
|
||||
active={menu && page === 2}
|
||||
onPointerEnter={enterMenu(2)}
|
||||
onPointerLeave={exitMenu}
|
||||
onPointerLeave={leaveMenu}
|
||||
/>
|
||||
<LinkItem
|
||||
text="业务定制"
|
||||
@@ -138,8 +146,7 @@ export default function Header(props: HeaderProps) {
|
||||
<Button
|
||||
theme="ghost"
|
||||
className="lg:hidden size-10"
|
||||
onPointerEnter={enterMenu(3)}
|
||||
onPointerLeave={exitMenu}
|
||||
onClick={toggleMobileMenu}
|
||||
>
|
||||
<MenuIcon/>
|
||||
</Button>
|
||||
@@ -168,7 +175,7 @@ export default function Header(props: HeaderProps) {
|
||||
: `delay-[0s,0s] opacity-0 py-0 pointer-events-none`,
|
||||
)}
|
||||
onPointerEnter={enterMenuContent}
|
||||
onPointerLeave={exitMenuContent}
|
||||
onPointerLeave={leaveMenuContent}
|
||||
>
|
||||
{pages[page]}
|
||||
</div>
|
||||
|
||||
@@ -1,16 +1,15 @@
|
||||
import {ReactNode} from 'react'
|
||||
import Wrap from '@/components/wrap'
|
||||
import Image, {StaticImageData} from 'next/image'
|
||||
import Link from 'next/link'
|
||||
import check_main from '@/assets/check-main.svg'
|
||||
import banner from './_assets/banner.webp'
|
||||
import map from './_assets/map.webp'
|
||||
import next from './_assets/next.svg'
|
||||
import s1_1 from './_assets/s1-1.webp'
|
||||
import s1_2 from './_assets/s1-2.webp'
|
||||
import s1_3 from './_assets/s1-3.webp'
|
||||
import s1_4 from './_assets/s1-4.webp'
|
||||
import s1_check from './_assets/s1-check.svg'
|
||||
import s3_main from './_assets/s3-main.webp'
|
||||
import s4_1_main from './_assets/s4-1-main.webp'
|
||||
import s4_2_main from './_assets/s4-2-main.webp'
|
||||
import s4_1_1 from './_assets/s4-1-1.webp'
|
||||
@@ -20,6 +19,7 @@ import s4_2_1 from './_assets/s4-2-1.webp'
|
||||
import s4_2_2 from './_assets/s4-2-2.webp'
|
||||
import s4_2_3 from './_assets/s4-2-3.webp'
|
||||
import FreeTrial from '@/components/free-trial'
|
||||
import {BookOpen, Smartphone, Settings, HelpCircle, Newspaper, FileText} from 'lucide-react'
|
||||
|
||||
export default function Home() {
|
||||
return (
|
||||
@@ -141,37 +141,27 @@ export default function Home() {
|
||||
|
||||
{/* 推荐文章 */}
|
||||
<Section title="推荐文章">
|
||||
<div className="flex gap-8 max-md:gap-4">
|
||||
<button className="px-4 max-md:-mx-4">
|
||||
<Image src={next} alt="prev" className="rotate-180"/>
|
||||
</button>
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-8">
|
||||
<ArticleCard
|
||||
icon={<BookOpen className="w-12 h-12"/>}
|
||||
title="浏览器设置代理教程"
|
||||
description="快速上手,5分钟学会在浏览器中配置代理服务器"
|
||||
href="/docs/browser-proxy"
|
||||
/>
|
||||
|
||||
<div
|
||||
className={[
|
||||
`shadow-[4px_4px_20px_4px] shadow-blue-50 rounded-lg`,
|
||||
`flex p-14 md:gap-14 max-md:flex-col max-md:p-4`,
|
||||
].join(' ')}>
|
||||
<Image src={s3_main} alt="tumb" className="w-2/3 md:flex-1 md:w-0 object-cover max-md:self-center"/>
|
||||
<div className="flex-2 flex flex-col justify-between gap-4">
|
||||
<h3 className="flex justify-between">
|
||||
<span className="text-xl">我是标题</span>
|
||||
<sub className="text-sm text-gray-500">2025-03-04</sub>
|
||||
</h3>
|
||||
<p className="text-gray-400 md:leading-12">
|
||||
我是内容我是内容我是内容我是内容我是内容我是容我是内容我是内容内容我是内容我是内容我是内我是内容我是内容我是内容我是内容我是内容...
|
||||
</p>
|
||||
<div className="flex justify-end">
|
||||
<a href="#" className="text-sm text-gray-500 flex items-center gap-4">
|
||||
更多详情
|
||||
<Image src={next} alt="more" className="h-4 fill-gray-400"/>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<ArticleCard
|
||||
icon={<Smartphone className="w-12 h-12"/>}
|
||||
title="Windows10 代理配置"
|
||||
description="详细图文教程,帮助你在 Windows 系统中设置代理"
|
||||
href="/docs/windows10-proxy"
|
||||
/>
|
||||
|
||||
<button className="px-4 max-md:-mx-4">
|
||||
<Image src={next} alt="prev"/>
|
||||
</button>
|
||||
<ArticleCard
|
||||
icon={<HelpCircle className="w-12 h-12"/>}
|
||||
title="常见问题总览"
|
||||
description="解决使用过程中遇到的各类问题,快速找到答案"
|
||||
href="/docs/faq-general"
|
||||
/>
|
||||
</div>
|
||||
</Section>
|
||||
</main>
|
||||
@@ -222,6 +212,43 @@ function Sec3Item(props: {
|
||||
)
|
||||
}
|
||||
|
||||
function ArticleCard(props: {
|
||||
icon: ReactNode
|
||||
title: string
|
||||
description: string
|
||||
href: string
|
||||
}) {
|
||||
return (
|
||||
<Link
|
||||
href={props.href}
|
||||
className={[
|
||||
`group block p-8 shadow-[4px_4px_20px_4px] shadow-blue-50 rounded-lg bg-white`,
|
||||
`transition-all duration-200`,
|
||||
].join(' ')}
|
||||
>
|
||||
<div className="flex flex-col items-center text-center gap-6">
|
||||
<div className="p-4 rounded-xl bg-linear-to-br from-blue-500 to-cyan-400 text-white group-hover:scale-110 transition-transform">
|
||||
{props.icon}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h3 className="text-xl font-semibold mb-3 group-hover:text-blue-600 transition-colors">
|
||||
{props.title}
|
||||
</h3>
|
||||
<p className="text-gray-500 text-sm leading-relaxed">
|
||||
{props.description}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="mt-2 text-blue-500 text-sm flex items-center gap-2 group-hover:gap-3 transition-all">
|
||||
<span>了解更多</span>
|
||||
<span className="text-lg">→</span>
|
||||
</div>
|
||||
</div>
|
||||
</Link>
|
||||
)
|
||||
}
|
||||
|
||||
function Sec4Item(props: {
|
||||
icon: StaticImageData
|
||||
title: string
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {ReactNode} from 'react'
|
||||
import {ReactNode, Suspense} from 'react'
|
||||
import {Metadata} from 'next'
|
||||
|
||||
export async function generateMetadata(): Promise<Metadata> {
|
||||
@@ -12,5 +12,9 @@ export type BillsLayoutProps = {
|
||||
}
|
||||
|
||||
export default async function BillsLayout(props: BillsLayoutProps) {
|
||||
return props.children
|
||||
return (
|
||||
<Suspense>
|
||||
{props.children}
|
||||
</Suspense>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ export default async function DashboardPage(props: DashboardPageProps) {
|
||||
if (!resp.success) {
|
||||
return (
|
||||
<div className="col-start-4 row-start-3 row-span-2 flex justify-center items-center">
|
||||
获取公告数据失败
|
||||
初始化数据失败
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user