Files
novalon-website/src/components/layout/footer.tsx
T
zhangxiang f3fc969bef test(mobile): add mobile E2E test suite (53 tests) and fix layout issues
Add comprehensive mobile testing coverage:
- Add chromium-mobile functional test project (iPhone 14, isMobile, hasTouch)
- Add mobile user journey tests (UJ-01/02/04/05/10 mobile variants)
- Add mobile performance baseline tests (FCP/LCP/load time)
- Add mobile accessibility tests (axe-core WCAG 2.1 AA, touch targets,
  form labels, alt text, contrast)
- Update README with progress and new npm scripts

Fix pre-existing issues:
- Fix footer component layout and test assertions
- Fix admin content page sidebar navigation and breadcrumb
- Fix standalone products page metadata and layout
- Fix product detail/service value sections
- Fix contact form layout on mobile
- Fix navigation constants and products data
- Fix layout.tsx CMS config and theme handling
- Fix erp-upgrade content layout
2026-08-03 18:32:29 +08:00

167 lines
6.9 KiB
TypeScript

'use client';
import { StaticLink } from '@/components/ui/static-link';
import Image from 'next/image';
import { Mail, MapPin } from 'lucide-react';
import { useSiteConfig } from '@/lib/site-config';
export function Footer() {
const config = useSiteConfig();
const productItems = (config.megaDropdown.products ?? [])
.flatMap(group => group.items)
.filter(item => item.href !== '#');
const solutionItems = (config.megaDropdown.solutions ?? [])
.flatMap(group => group.items);
return (
<footer className="bg-[#0A0E14] text-white relative overflow-hidden" data-testid="footer" role="contentinfo">
<div className="max-w-container mx-auto px-4 sm:px-6 lg:px-10">
<div className="grid grid-cols-2 md:grid-cols-4 lg:grid-cols-12 gap-10 lg:gap-12 py-16 lg:py-20">
<div data-testid="card-brand" className="col-span-2 lg:col-span-4">
<div className="mb-6">
<StaticLink href="/" className="inline-block group" aria-label="返回首页">
<Image
src="/logo-white.svg"
alt={config.name}
width={180}
height={45}
className="w-auto h-10 md:h-12 transition-transform duration-normal ease-out group-hover:scale-[1.02]"
loading="eager"
priority
/>
</StaticLink>
</div>
<p className="text-gray-300 text-sm leading-relaxed max-w-md">
{config.description}
</p>
</div>
<div data-testid="card-products" className="lg:col-span-2">
<h3 className="font-semibold text-sm mb-5 text-white tracking-widest uppercase">产品</h3>
<ul className="space-y-3 [&_li]:p-0 [&_li]:m-0 [&_li]:static [&_li::before]:hidden">
{productItems.map((item) => (
<li key={item.id}>
<StaticLink
href={item.href}
className="text-gray-300 hover:text-white transition-colors duration-200 text-sm whitespace-nowrap"
>
{item.title}
</StaticLink>
</li>
))}
</ul>
</div>
<div data-testid="card-solutions" className="lg:col-span-2">
<h3 className="font-semibold text-sm mb-5 text-white tracking-widest uppercase">解决方案</h3>
<ul className="space-y-3 [&_li]:p-0 [&_li]:m-0 [&_li]:static [&_li::before]:hidden">
{solutionItems.map((item) => (
<li key={item.id}>
<StaticLink
href={item.href}
className="text-gray-300 hover:text-white transition-colors duration-200 text-sm whitespace-nowrap"
>
{item.title}
</StaticLink>
</li>
))}
</ul>
</div>
<div data-testid="card-contact" className="col-span-2 lg:col-span-4">
<h3 className="font-semibold text-sm mb-5 text-white tracking-widest uppercase">联系我们</h3>
<ul className="space-y-4 mb-8 [&_li]:p-0 [&_li]:m-0 [&_li]:static [&_li::before]:hidden">
<li className="flex items-start gap-3">
<MapPin className="w-4 h-4 text-gray-400 mt-0.5 shrink-0" />
<span className="text-gray-300 text-sm leading-relaxed">{config.address}</span>
</li>
<li className="flex items-center gap-3">
<Mail className="w-4 h-4 text-gray-400 shrink-0" />
<a
href={`mailto:${config.email}`}
className="text-gray-300 hover:text-white transition-colors duration-200 text-sm"
>
{config.email}
</a>
</li>
</ul>
<div className="flex gap-6">
<div>
<p className="text-xs text-gray-400 mb-3 tracking-wide">关注公众号</p>
<div className="inline-block p-2 border border-gray-800 bg-gray-900">
<Image
src="/images/qrcode.webp"
alt="微信公众号二维码"
width={96}
height={96}
className="w-24 h-24"
loading="lazy"
/>
</div>
</div>
<div>
<p className="text-xs text-gray-400 mb-3 tracking-wide">业务咨询</p>
<div className="inline-block p-2 border border-gray-800 bg-gray-900">
<Image
src="/images/wechat-business-qr.webp"
alt="业务咨询微信二维码"
width={96}
height={96}
className="w-24 h-24"
loading="lazy"
/>
</div>
</div>
</div>
</div>
</div>
<div className="border-t border-gray-800 pt-6 pb-[calc(8rem+env(safe-area-inset-bottom,0px))] md:pb-8">
<div className="flex flex-col md:flex-row justify-between items-start md:items-center gap-6 mb-6">
<p className="text-gray-300 text-xs">
© {new Date().getFullYear()} {config.name}. 版权所有.
</p>
<div className="flex gap-6">
<StaticLink href="/privacy" className="text-gray-300 hover:text-white text-xs transition-colors duration-200">
隐私政策
</StaticLink>
<StaticLink href="/terms" className="text-gray-300 hover:text-white text-xs transition-colors duration-200">
服务条款
</StaticLink>
</div>
</div>
<div className="flex flex-col sm:flex-row justify-center items-center gap-2 sm:gap-4 pt-4 text-[0.8125rem]">
<a
href="https://beian.miit.gov.cn/"
target="_blank"
rel="noopener noreferrer"
className="text-gray-300 hover:text-white transition-colors duration-200 inline-flex items-center"
>
{config.icp}
</a>
<span className="hidden sm:inline text-gray-500">|</span>
<a
href="https://beian.mps.gov.cn/#/query/webSearch?code=51010602003285"
target="_blank"
rel="noreferrer"
className="text-gray-300 hover:text-white transition-colors duration-200 inline-flex items-center gap-1.5"
>
<Image
src="/images/beian-icon.png"
alt="公安备案"
width={14}
height={14}
className="w-3.5 h-3.5 opacity-80"
loading="lazy"
/>
{config.police}
</a>
</div>
</div>
</div>
</footer>
);
}