fix(regression): resolve dogfood findings across marketing, auth, e2e and docs

- Fix list-to-detail navigation on product/service/solution/case pages
- Fix soft 404 on service detail by removing (marketing)/loading.tsx and using force-dynamic
- Fix contact form submission feedback and news placeholder image handling
- Unify SSR/client authentication state in auth.ts
- Add "新闻动态" to main navigation
- Fix Playwright storageState path and Firefox footer link flakiness
- Add E2E coverage for nav dropdown, cases filter and auth token parsing
- Update visual regression baselines (desktop/tablet/mobile, chromium/webkit/firefox)
- Update README, lessons-learned and add REGRESSION_REPORT_2026-07-27.md
- Ignore .lighthouseci/ and heading-hierarchy-report.json
This commit is contained in:
2026-07-27 07:39:11 +08:00
parent 10404dbb36
commit 2653a3730c
97 changed files with 659 additions and 187 deletions
@@ -2,6 +2,7 @@
import { motion } from 'framer-motion';
import { ArrowUpRight, CheckCircle2 } from 'lucide-react';
import { StaticLink } from '@/components/ui/static-link';
import type { Service } from '@/lib/constants/services';
const EASE_OUT = [0.22, 1, 0.36, 1] as const;
@@ -192,48 +193,51 @@ function ServicesGridSection({ services }: { services?: Service[] }) {
<div className="grid md:grid-cols-2 gap-px bg-border-primary">
{displayServices.map((service, i) => (
<motion.a
<motion.div
key={service.id}
href={`/services/${service.id}`}
initial={{ opacity: 0, y: 30 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true, margin: '-60px' }}
transition={{ duration: 0.6, delay: i * 0.08, ease: EASE_OUT }}
className="group relative block p-8 sm:p-10 md:p-12 transition-all duration-500 hover:bg-bg-secondary hover:shadow-lg hover:-translate-y-1 bg-white border border-transparent hover:border-border-primary"
>
<div className="relative z-10">
<h3 className="text-xl sm:text-2xl font-bold text-ink group-hover:text-brand transition-colors duration-300 mb-3">
{service.title}
</h3>
<StaticLink
href={`/services/${service.id}`}
className="group relative block p-8 sm:p-10 md:p-12 transition-all duration-500 hover:bg-bg-secondary hover:shadow-lg hover:-translate-y-1 bg-white border border-transparent hover:border-border-primary"
>
<div className="relative z-10">
<h3 className="text-xl sm:text-2xl font-bold text-ink group-hover:text-brand transition-colors duration-300 mb-3">
{service.title}
</h3>
<p className="text-text-secondary leading-relaxed mb-6 text-[15px]">
{service.description}
</p>
<p className="text-text-secondary leading-relaxed mb-6 text-[15px]">
{service.description}
</p>
<ul className="space-y-2 mb-6">
{service.capabilities.map((cap) => (
<li key={cap} className="flex items-start gap-2 text-sm text-text-secondary">
<CheckCircle2 className="w-4 h-4 text-brand shrink-0 mt-0.5" />
{cap}
</li>
))}
</ul>
<ul className="space-y-2 mb-6">
{service.capabilities.map((cap) => (
<li key={cap} className="flex items-start gap-2 text-sm text-text-secondary">
<CheckCircle2 className="w-4 h-4 text-brand shrink-0 mt-0.5" />
{cap}
</li>
))}
</ul>
<div className="flex gap-6 pt-5 border-t border-border-primary mb-6">
{service.metrics.map((m) => (
<div key={m.label}>
<div className="text-xl font-bold text-ink">{m.value}</div>
<div className="text-xs text-text-muted mt-1">{m.label}</div>
</div>
))}
<div className="flex gap-6 pt-5 border-t border-border-primary mb-6">
{service.metrics.map((m) => (
<div key={m.label}>
<div className="text-xl font-bold text-ink">{m.value}</div>
<div className="text-xs text-text-muted mt-1">{m.label}</div>
</div>
))}
</div>
<div className="inline-flex items-center gap-2 text-sm font-semibold text-text-secondary group-hover:text-brand transition-colors duration-300">
<span>了解详情</span>
<ArrowUpRight className="w-4 h-4 group-hover:translate-x-0.5 group-hover:-translate-y-0.5 transition-transform duration-300" />
</div>
</div>
<div className="inline-flex items-center gap-2 text-sm font-semibold text-text-secondary group-hover:text-brand transition-colors duration-300">
<span>了解详情</span>
<ArrowUpRight className="w-4 h-4 group-hover:translate-x-0.5 group-hover:-translate-y-0.5 transition-transform duration-300" />
</div>
</div>
</motion.a>
</StaticLink>
</motion.div>
))}
</div>
</div>