8 changed files with 480 additions and 256 deletions
@ -1,27 +1,120 @@ |
|||
// import HeroSection from '@/components/sections/HeroSection';
|
|||
// import FeaturesSection from '@/components/sections/FeaturesSection';
|
|||
// import CasesSection from '@/components/sections/CasesSection';
|
|||
// import PartnersSection from '@/components/sections/PartnersSection';
|
|||
// import ContactSection from '@/components/sections/ContactSection';
|
|||
import SiteInfoDisplay from '@/components/sections/SiteInfoDisplay'; |
|||
import NavigationDisplay from '@/components/sections/NavigationDisplay'; |
|||
|
|||
export default function Home() { |
|||
return ( |
|||
<main> |
|||
<div className={'bg-gray-200'}>Main</div> |
|||
{/* 英雄区域 */} |
|||
{/*<HeroSection />*/} |
|||
<div className="min-h-screen bg-gray-50"> |
|||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-12"> |
|||
<div className="text-center mb-12"> |
|||
<h1 className="text-4xl font-bold text-gray-900 mb-4"> |
|||
Zustand 全局状态管理演示 |
|||
</h1> |
|||
<p className="text-lg text-gray-600 max-w-2xl mx-auto"> |
|||
这个页面展示了如何使用 Zustand 管理全局的站点信息, |
|||
实现数据缓存和跨组件共享。 |
|||
</p> |
|||
</div> |
|||
|
|||
{/* 产品服务 */} |
|||
{/*<FeaturesSection />*/} |
|||
<div className="space-y-12"> |
|||
{/* 站点信息展示 */} |
|||
<div> |
|||
<h2 className="text-2xl font-semibold text-gray-900 mb-4"> |
|||
站点信息展示 |
|||
</h2> |
|||
<SiteInfoDisplay /> |
|||
</div> |
|||
|
|||
{/* 客户案例 */} |
|||
{/*<CasesSection />*/} |
|||
{/* 导航菜单展示 */} |
|||
<div> |
|||
<h2 className="text-2xl font-semibold text-gray-900 mb-4"> |
|||
导航菜单展示 |
|||
</h2> |
|||
<NavigationDisplay /> |
|||
</div> |
|||
|
|||
{/* 合作伙伴 */} |
|||
{/*<PartnersSection />*/} |
|||
{/* 功能说明 */} |
|||
<div> |
|||
<h2 className="text-2xl font-semibold text-gray-900 mb-4"> |
|||
功能特点 |
|||
</h2> |
|||
<div className="bg-white border border-gray-200 p-6 rounded-lg shadow-sm"> |
|||
<ul className="space-y-4"> |
|||
<li className="flex items-start"> |
|||
<div className="flex-shrink-0 w-6 h-6 bg-green-100 rounded-full flex items-center justify-center mt-0.5"> |
|||
<svg className="w-4 h-4 text-green-600" fill="currentColor" viewBox="0 0 20 20"> |
|||
<path fillRule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clipRule="evenodd" /> |
|||
</svg> |
|||
</div> |
|||
<div className="ml-3"> |
|||
<h3 className="text-sm font-medium text-gray-900">自动缓存</h3> |
|||
<p className="text-sm text-gray-600">30分钟内不重复请求接口</p> |
|||
</div> |
|||
</li> |
|||
|
|||
{/* 联系我们 */} |
|||
{/*<ContactSection />*/} |
|||
</main> |
|||
<li className="flex items-start"> |
|||
<div className="flex-shrink-0 w-6 h-6 bg-green-100 rounded-full flex items-center justify-center mt-0.5"> |
|||
<svg className="w-4 h-4 text-green-600" fill="currentColor" viewBox="0 0 20 20"> |
|||
<path fillRule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clipRule="evenodd" /> |
|||
</svg> |
|||
</div> |
|||
<div className="ml-3"> |
|||
<h3 className="text-sm font-medium text-gray-900">持久化存储</h3> |
|||
<p className="text-sm text-gray-600">数据存储在 sessionStorage 中</p> |
|||
</div> |
|||
</li> |
|||
|
|||
<li className="flex items-start"> |
|||
<div className="flex-shrink-0 w-6 h-6 bg-green-100 rounded-full flex items-center justify-center mt-0.5"> |
|||
<svg className="w-4 h-4 text-green-600" fill="currentColor" viewBox="0 0 20 20"> |
|||
<path fillRule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clipRule="evenodd" /> |
|||
</svg> |
|||
</div> |
|||
<div className="ml-3"> |
|||
<h3 className="text-sm font-medium text-gray-900">全局共享</h3> |
|||
<p className="text-sm text-gray-600">任意组件都可以访问站点信息</p> |
|||
</div> |
|||
</li> |
|||
|
|||
<li className="flex items-start"> |
|||
<div className="flex-shrink-0 w-6 h-6 bg-green-100 rounded-full flex items-center justify-center mt-0.5"> |
|||
<svg className="w-4 h-4 text-green-600" fill="currentColor" viewBox="0 0 20 20"> |
|||
<path fillRule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clipRule="evenodd" /> |
|||
</svg> |
|||
</div> |
|||
<div className="ml-3"> |
|||
<h3 className="text-sm font-medium text-gray-900">错误处理</h3> |
|||
<p className="text-sm text-gray-600">自动重试和错误状态管理</p> |
|||
</div> |
|||
</li> |
|||
|
|||
<li className="flex items-start"> |
|||
<div className="flex-shrink-0 w-6 h-6 bg-green-100 rounded-full flex items-center justify-center mt-0.5"> |
|||
<svg className="w-4 h-4 text-green-600" fill="currentColor" viewBox="0 0 20 20"> |
|||
<path fillRule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clipRule="evenodd" /> |
|||
</svg> |
|||
</div> |
|||
<div className="ml-3"> |
|||
<h3 className="text-sm font-medium text-gray-900">导航菜单管理</h3> |
|||
<p className="text-sm text-gray-600">支持顶部和底部导航菜单的动态加载</p> |
|||
</div> |
|||
</li> |
|||
|
|||
<li className="flex items-start"> |
|||
<div className="flex-shrink-0 w-6 h-6 bg-green-100 rounded-full flex items-center justify-center mt-0.5"> |
|||
<svg className="w-4 h-4 text-green-600" fill="currentColor" viewBox="0 0 20 20"> |
|||
<path fillRule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clipRule="evenodd" /> |
|||
</svg> |
|||
</div> |
|||
<div className="ml-3"> |
|||
<h3 className="text-sm font-medium text-gray-900">TypeScript 支持</h3> |
|||
<p className="text-sm text-gray-600">完整的类型安全保障</p> |
|||
</div> |
|||
</li> |
|||
</ul> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
); |
|||
} |
|||
|
@ -1,49 +1,124 @@ |
|||
'use client'; |
|||
import { useState, useEffect } from 'react'; |
|||
import {useState} from 'react'; |
|||
import Link from 'next/link'; |
|||
import { usePathname } from 'next/navigation'; |
|||
import {getSiteInfo} from "@/api/layout"; |
|||
import {CmsWebsite} from "@/api/cms/cmsWebsite/model"; |
|||
|
|||
import Image from 'next/image'; |
|||
import {usePathname} from 'next/navigation'; |
|||
import {useSiteInfo} from '@/hooks/useSiteInfo'; |
|||
|
|||
const Header = () => { |
|||
const [config, setConfig] = useState<CmsWebsite>({}) |
|||
const [isMenuOpen, setIsMenuOpen] = useState(false); |
|||
const pathname = usePathname(); |
|||
|
|||
const navigation = [ |
|||
{ name: '首页', href: '/' }, |
|||
{ name: '产品', href: '/products' }, |
|||
{ name: '解决方案', href: '/solutions' }, |
|||
{ name: '案例', href: '/cases' }, |
|||
{ name: '关于', href: '/about' }, |
|||
{ name: '联系', href: '/contact' }, |
|||
]; |
|||
|
|||
const isActive = (href: string) => { |
|||
if (href === '/') { |
|||
return pathname === '/'; |
|||
} |
|||
return pathname.startsWith(href); |
|||
}; |
|||
|
|||
const reload = () => { |
|||
getSiteInfo().then(data => { |
|||
if(data){ |
|||
setConfig(data); |
|||
} |
|||
}) |
|||
} |
|||
|
|||
useEffect(() => { |
|||
reload(); |
|||
}, []); |
|||
|
|||
return ( |
|||
<header className="bg-red-100 text-2xl shadow-sm border-b border-gray-100 sticky top-0 z-50"> |
|||
Top |
|||
</header> |
|||
); |
|||
const [isMenuOpen, setIsMenuOpen] = useState(false); |
|||
const pathname = usePathname(); |
|||
|
|||
// 使用全局状态管理的站点信息
|
|||
const {siteInfo, loading, error, refresh} = useSiteInfo({forceRefresh: true}); |
|||
|
|||
const navigation = [ |
|||
{name: '首页', href: '/'}, |
|||
{name: '产品', href: '/products'}, |
|||
{name: '解决方案', href: '/solutions'}, |
|||
{name: '案例', href: '/cases'}, |
|||
{name: '关于', href: '/about'}, |
|||
{name: '联系', href: '/contact'}, |
|||
]; |
|||
|
|||
const isActive = (href: string) => { |
|||
if (href === '/') { |
|||
return pathname === '/'; |
|||
} |
|||
return pathname.startsWith(href); |
|||
}; |
|||
|
|||
return ( |
|||
<header className="bg-white shadow-sm border-b border-gray-100 sticky top-0 z-50"> |
|||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8"> |
|||
<div className="flex justify-between items-center h-16"> |
|||
{/* Logo 和站点名称 */} |
|||
<div className="flex items-center"> |
|||
<Link href="/" className="flex items-center space-x-2"> |
|||
{siteInfo?.websiteLogo && ( |
|||
<Image |
|||
src={siteInfo.websiteLogo} |
|||
alt={siteInfo.websiteName || '网站Logo'} |
|||
width={107} |
|||
height={24} |
|||
className="h-8 w-auto" |
|||
/> |
|||
)} |
|||
{/*<span className="text-xl font-bold text-gray-900">*/} |
|||
{/* {siteInfo?.websiteName || '加载中...'}*/} |
|||
{/*</span>*/} |
|||
</Link> |
|||
</div> |
|||
|
|||
{/* 导航菜单 */} |
|||
<nav className="hidden md:flex space-x-8"> |
|||
{navigation.map((item) => ( |
|||
<Link |
|||
key={item.name} |
|||
href={item.href} |
|||
className={`px-3 py-2 text-sm font-medium transition-colors ${ |
|||
isActive(item.href) |
|||
? 'text-blue-600 border-b-2 border-blue-600' |
|||
: 'text-gray-700 hover:text-blue-600' |
|||
}`}
|
|||
> |
|||
{item.name} |
|||
</Link> |
|||
))} |
|||
</nav> |
|||
|
|||
{/* 加载状态和错误处理 */} |
|||
<div className="flex items-center space-x-4"> |
|||
{loading && ( |
|||
<div className="text-sm text-gray-500">加载中...</div> |
|||
)} |
|||
{error && ( |
|||
<button |
|||
onClick={refresh} |
|||
className="text-sm text-red-600 hover:text-red-800" |
|||
title="点击重试" |
|||
> |
|||
加载失败,点击重试 |
|||
</button> |
|||
)} |
|||
|
|||
{/* 移动端菜单按钮 */} |
|||
<button |
|||
onClick={() => setIsMenuOpen(!isMenuOpen)} |
|||
className="md:hidden p-2 rounded-md text-gray-700 hover:text-blue-600" |
|||
> |
|||
<svg className="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor"> |
|||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} |
|||
d="M4 6h16M4 12h16M4 18h16"/> |
|||
</svg> |
|||
</button> |
|||
</div> |
|||
</div> |
|||
|
|||
{/* 移动端菜单 */} |
|||
{isMenuOpen && ( |
|||
<div className="md:hidden"> |
|||
<div className="px-2 pt-2 pb-3 space-y-1 sm:px-3 border-t border-gray-200"> |
|||
{navigation.map((item) => ( |
|||
<Link |
|||
key={item.name} |
|||
href={item.href} |
|||
className={`block px-3 py-2 text-base font-medium transition-colors ${ |
|||
isActive(item.href) |
|||
? 'text-blue-600 bg-blue-50' |
|||
: 'text-gray-700 hover:text-blue-600 hover:bg-gray-50' |
|||
}`}
|
|||
onClick={() => setIsMenuOpen(false)} |
|||
> |
|||
{item.name} |
|||
</Link> |
|||
))} |
|||
</div> |
|||
</div> |
|||
)} |
|||
</div> |
|||
</header> |
|||
); |
|||
}; |
|||
|
|||
export default Header; |
|||
|
@ -1,165 +0,0 @@ |
|||
'use client'; |
|||
import { useState, useEffect } from 'react'; |
|||
import Link from 'next/link'; |
|||
import { usePathname } from 'next/navigation'; |
|||
import {getSiteInfo} from "@/api/layout"; |
|||
import {CmsWebsite} from "@/api/cms/cmsWebsite/model"; |
|||
|
|||
|
|||
const Header = () => { |
|||
const [config, setConfig] = useState<CmsWebsite>({}) |
|||
const [isMenuOpen, setIsMenuOpen] = useState(false); |
|||
const pathname = usePathname(); |
|||
|
|||
const navigation = [ |
|||
{ name: '首页', href: '/' }, |
|||
{ name: '产品', href: '/products' }, |
|||
{ name: '解决方案', href: '/solutions' }, |
|||
{ name: '案例', href: '/cases' }, |
|||
{ name: '关于', href: '/about' }, |
|||
{ name: '联系', href: '/contact' }, |
|||
]; |
|||
|
|||
const isActive = (href: string) => { |
|||
if (href === '/') { |
|||
return pathname === '/'; |
|||
} |
|||
return pathname.startsWith(href); |
|||
}; |
|||
|
|||
const reload = () => { |
|||
getSiteInfo().then(data => { |
|||
console.log(data,'data') |
|||
if(data){ |
|||
setConfig(data); |
|||
} |
|||
}) |
|||
} |
|||
|
|||
useEffect(() => { |
|||
reload(); |
|||
}, []); |
|||
|
|||
return ( |
|||
<header className="bg-white shadow-sm border-b border-gray-100 sticky top-0 z-50"> |
|||
<div className="container mx-auto px-4"> |
|||
<div className="flex items-center justify-between h-16"> |
|||
{/* Logo */} |
|||
<div className="flex-shrink-0"> |
|||
<Link href="/" className="text-xl font-bold text-gray-800"> |
|||
= {config?.websiteName} = |
|||
</Link> |
|||
</div> |
|||
|
|||
{/* Desktop Navigation */} |
|||
<nav className="hidden md:block"> |
|||
<div className="flex items-center space-x-8"> |
|||
{navigation.map((item) => ( |
|||
<Link |
|||
key={item.name} |
|||
href={item.href} |
|||
className={`text-sm font-medium transition-colors duration-300 ${ |
|||
isActive(item.href) |
|||
? 'text-blue-600' |
|||
: 'text-gray-700 hover:text-blue-600' |
|||
}`}
|
|||
> |
|||
{item.name} |
|||
</Link> |
|||
))} |
|||
</div> |
|||
</nav> |
|||
|
|||
{/* Language Switch & CTA */} |
|||
<div className="hidden md:flex items-center space-x-4"> |
|||
<div className="flex items-center space-x-2 text-sm text-gray-600"> |
|||
<span className="cursor-pointer hover:text-blue-600">中文</span> |
|||
<span>|</span> |
|||
<span className="cursor-pointer hover:text-blue-600">EN</span> |
|||
</div> |
|||
<Link href="/contact" className="btn btn-primary text-sm"> |
|||
免费咨询 |
|||
</Link> |
|||
</div> |
|||
|
|||
{/* Mobile menu button */} |
|||
<div className="md:hidden"> |
|||
<button |
|||
onClick={() => setIsMenuOpen(!isMenuOpen)} |
|||
className="inline-flex items-center justify-center p-2 rounded-md text-gray-400 hover:text-gray-500 hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-inset focus:ring-blue-500" |
|||
aria-expanded="false" |
|||
> |
|||
<span className="sr-only">打开主菜单</span> |
|||
{!isMenuOpen ? ( |
|||
<svg |
|||
className="block h-6 w-6" |
|||
xmlns="http://www.w3.org/2000/svg" |
|||
fill="none" |
|||
viewBox="0 0 24 24" |
|||
stroke="currentColor" |
|||
aria-hidden="true" |
|||
> |
|||
<path |
|||
strokeLinecap="round" |
|||
strokeLinejoin="round" |
|||
strokeWidth={2} |
|||
d="M4 6h16M4 12h16M4 18h16" |
|||
/> |
|||
</svg> |
|||
) : ( |
|||
<svg |
|||
className="block h-6 w-6" |
|||
xmlns="http://www.w3.org/2000/svg" |
|||
fill="none" |
|||
viewBox="0 0 24 24" |
|||
stroke="currentColor" |
|||
aria-hidden="true" |
|||
> |
|||
<path |
|||
strokeLinecap="round" |
|||
strokeLinejoin="round" |
|||
strokeWidth={2} |
|||
d="M6 18L18 6M6 6l12 12" |
|||
/> |
|||
</svg> |
|||
)} |
|||
</button> |
|||
</div> |
|||
</div> |
|||
|
|||
{/* Mobile Navigation */} |
|||
{isMenuOpen && ( |
|||
<div className="md:hidden"> |
|||
<div className="px-2 pt-2 pb-3 space-y-1 sm:px-3 bg-white border-t border-gray-200"> |
|||
{navigation.map((item) => ( |
|||
<Link |
|||
key={item.name} |
|||
href={item.href} |
|||
className={`block px-3 py-2 rounded-md text-base font-medium transition-colors duration-300 ${ |
|||
isActive(item.href) |
|||
? 'text-blue-600 bg-blue-50' |
|||
: 'text-gray-700 hover:text-blue-600 hover:bg-gray-50' |
|||
}`}
|
|||
onClick={() => setIsMenuOpen(false)} |
|||
> |
|||
{item.name} |
|||
</Link> |
|||
))} |
|||
<div className="px-3 py-2"> |
|||
<Link |
|||
href="/contact" |
|||
className="btn btn-primary w-full" |
|||
onClick={() => setIsMenuOpen(false)} |
|||
> |
|||
免费咨询 |
|||
</Link> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
)} |
|||
</div> |
|||
</header> |
|||
); |
|||
}; |
|||
|
|||
export default Header; |
Loading…
Reference in new issue