fix(marketing): resolve dogfood findings on cases, products, and contact
修复首页/案例/产品/联系页 dogfood 测试发现的 7 个问题: - 案例页行业筛选按钮失效 - 产品矩阵页计数器显示 "0+" - ERP 产品详情页核心功能区空白占位 - 联系表单无提交反馈 - 服务卡片图标被屏幕阅读器读取 - 产品卡片链接文本重复类别标签 - 联系页装饰图标缺少 aria-hidden 添加 dogfood-regression-output 报告与截图。
This commit is contained in:
@@ -243,6 +243,9 @@ export default function CasesContentV3({
|
||||
{industries.map((industry) => (
|
||||
<button
|
||||
key={industry.id}
|
||||
type="button"
|
||||
role="radio"
|
||||
aria-checked={selectedIndustry === industry.id}
|
||||
onClick={() => setSelectedIndustry(industry.id)}
|
||||
className={cn(
|
||||
'px-4 py-2 text-xs font-medium transition-all duration-300',
|
||||
|
||||
@@ -281,7 +281,7 @@ function ContactFormContent({ data }: { data: ContactData }) {
|
||||
<h2 className="text-xl font-bold text-ink mb-8">{data.contactTitle || ''}</h2>
|
||||
<div className="space-y-6" data-testid="contact-info">
|
||||
<div className="flex items-start gap-4" data-testid="email-info">
|
||||
<div className="w-12 h-12 border border-border-primary bg-white flex items-center justify-center shrink-0">
|
||||
<div className="w-12 h-12 border border-border-primary bg-white flex items-center justify-center shrink-0" aria-hidden="true">
|
||||
<Mail className="w-5 h-5 text-text-secondary" />
|
||||
</div>
|
||||
<div>
|
||||
@@ -297,7 +297,7 @@ function ContactFormContent({ data }: { data: ContactData }) {
|
||||
</div>
|
||||
|
||||
<div className="flex items-start gap-4" data-testid="address-info">
|
||||
<div className="w-12 h-12 border border-border-primary bg-white flex items-center justify-center shrink-0">
|
||||
<div className="w-12 h-12 border border-border-primary bg-white flex items-center justify-center shrink-0" aria-hidden="true">
|
||||
<MapPin className="w-5 h-5 text-text-secondary" />
|
||||
</div>
|
||||
<div>
|
||||
@@ -313,7 +313,7 @@ function ContactFormContent({ data }: { data: ContactData }) {
|
||||
<div className="relative border border-border-primary bg-white p-8 overflow-hidden">
|
||||
<div className="absolute top-0 left-0 bottom-0 w-0.5 bg-brand/60" />
|
||||
<div className="flex items-center gap-3 mb-4">
|
||||
<Clock className="w-5 h-5 text-brand" />
|
||||
<Clock className="w-5 h-5 text-brand" aria-hidden="true" />
|
||||
<h2 className="text-base font-bold text-ink">{data.workHoursTitle || ''}</h2>
|
||||
</div>
|
||||
<div className="flex justify-between" data-testid="work-hours-row">
|
||||
@@ -325,7 +325,7 @@ function ContactFormContent({ data }: { data: ContactData }) {
|
||||
<div className="relative border border-border-primary bg-white p-8 overflow-hidden">
|
||||
<div className="absolute top-0 left-0 bottom-0 w-0.5 bg-brand/60" />
|
||||
<div className="flex items-center gap-3 mb-4">
|
||||
<HeadphonesIcon className="w-5 h-5 text-text-secondary" />
|
||||
<HeadphonesIcon className="w-5 h-5 text-text-secondary" aria-hidden="true" />
|
||||
<h2 className="text-base font-bold text-ink">{data.commitmentTitle || ''}</h2>
|
||||
</div>
|
||||
<div className="space-y-4">
|
||||
|
||||
@@ -119,7 +119,7 @@ function FeaturesSection({ features }: FeaturesSectionProps) {
|
||||
<div className="flex items-center gap-5">
|
||||
<div className="w-14 h-px bg-brand" />
|
||||
<span className="text-[11px] tracking-[0.4em] uppercase font-bold text-brand">
|
||||
Core Features
|
||||
核心功能
|
||||
</span>
|
||||
<div className="w-14 h-px bg-brand" />
|
||||
</div>
|
||||
@@ -129,25 +129,25 @@ function FeaturesSection({ features }: FeaturesSectionProps) {
|
||||
</h2>
|
||||
</ScrollReveal>
|
||||
|
||||
<div className="grid md:grid-cols-2 lg:grid-cols-3 gap-px bg-border-primary">
|
||||
<StaggerReveal staggerDelay={0.08} delayChildren={0.05}>
|
||||
{features.map((feature, idx) => (
|
||||
<div
|
||||
key={idx}
|
||||
className="group relative p-8 bg-white hover:bg-bg-secondary transition-all duration-500"
|
||||
>
|
||||
<div className="absolute top-0 left-0 h-full w-1 scale-y-0 group-hover:scale-y-100 transition-transform duration-700 origin-top bg-brand" />
|
||||
|
||||
<div className="flex items-start gap-5">
|
||||
<div className="w-10 h-10 rounded-xl bg-brand-soft flex items-center justify-center text-brand shrink-0 mt-0.5">
|
||||
<Check className="w-5 h-5" />
|
||||
</div>
|
||||
<p className="text-lg text-ink font-medium leading-relaxed">{feature}</p>
|
||||
<StaggerReveal
|
||||
className="grid md:grid-cols-2 lg:grid-cols-3 gap-px bg-border-primary"
|
||||
staggerDelay={0.08}
|
||||
delayChildren={0.05}
|
||||
>
|
||||
{features.map((feature, idx) => (
|
||||
<div
|
||||
key={idx}
|
||||
className="group relative p-8 bg-white hover:bg-bg-secondary transition-all duration-500"
|
||||
>
|
||||
<div className="flex items-start gap-5">
|
||||
<div className="w-10 h-10 rounded-xl bg-brand-soft flex items-center justify-center text-brand shrink-0 mt-0.5">
|
||||
<Check className="w-5 h-5" />
|
||||
</div>
|
||||
<p className="text-lg text-ink font-medium leading-relaxed">{feature}</p>
|
||||
</div>
|
||||
))}
|
||||
</StaggerReveal>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</StaggerReveal>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
@@ -166,7 +166,7 @@ function BenefitsSection({ benefits }: BenefitsSectionProps) {
|
||||
<div className="max-w-container mx-auto px-4 sm:px-6 lg:px-10">
|
||||
<div className="grid lg:grid-cols-2 gap-20 items-start">
|
||||
<ScrollReveal>
|
||||
<SectionLabel>Benefits</SectionLabel>
|
||||
<SectionLabel>产品价值</SectionLabel>
|
||||
<h2 className="text-3xl md:text-4xl lg:text-5xl font-bold text-ink tracking-tight leading-tight mb-8">
|
||||
产品价值
|
||||
</h2>
|
||||
@@ -182,7 +182,6 @@ function BenefitsSection({ benefits }: BenefitsSectionProps) {
|
||||
key={idx}
|
||||
className="group relative p-8 bg-white hover:bg-bg-secondary transition-all duration-500"
|
||||
>
|
||||
<div className="absolute left-0 top-0 bottom-0 w-1 bg-brand scale-y-0 group-hover:scale-y-100 transition-transform duration-500 origin-top" />
|
||||
<div className="flex items-start gap-6">
|
||||
<div className="w-12 h-12 rounded-2xl bg-brand-soft/50 flex items-center justify-center text-brand shrink-0">
|
||||
<TrendingUp className="w-6 h-6" />
|
||||
@@ -215,7 +214,7 @@ function ProcessSection({ process }: ProcessSectionProps) {
|
||||
<div className="flex items-center gap-5">
|
||||
<div className="w-14 h-px bg-brand" />
|
||||
<span className="text-[11px] tracking-[0.4em] uppercase font-bold text-brand">
|
||||
Implementation
|
||||
实施流程
|
||||
</span>
|
||||
<div className="w-14 h-px bg-brand" />
|
||||
</div>
|
||||
@@ -269,7 +268,7 @@ function CaseStudiesSection({ caseStudies }: CaseStudiesSectionProps) {
|
||||
<div className="flex items-center gap-5">
|
||||
<div className="w-14 h-px bg-brand" />
|
||||
<span className="text-[11px] tracking-[0.4em] uppercase font-bold text-brand">
|
||||
Case Studies
|
||||
客户案例
|
||||
</span>
|
||||
<div className="w-14 h-px bg-brand" />
|
||||
</div>
|
||||
@@ -338,7 +337,7 @@ function CertificationsSection({ certifications }: CertificationsSectionProps) {
|
||||
<div className="flex items-center gap-5">
|
||||
<div className="w-14 h-px bg-brand" />
|
||||
<span className="text-[11px] tracking-[0.4em] uppercase font-bold text-brand">
|
||||
Certifications
|
||||
资质认证
|
||||
</span>
|
||||
<div className="w-14 h-px bg-brand" />
|
||||
</div>
|
||||
@@ -387,7 +386,7 @@ function CTASection({ product }: CTASectionProps) {
|
||||
<div className="flex items-center gap-5">
|
||||
<div className="w-14 h-px bg-brand" />
|
||||
<span className="text-[11px] tracking-[0.4em] uppercase font-bold text-brand">
|
||||
Get Started
|
||||
开始使用
|
||||
</span>
|
||||
<div className="w-14 h-px bg-brand" />
|
||||
</div>
|
||||
@@ -444,15 +443,17 @@ export default function ProductDetailContentV3({ product }: ProductDetailContent
|
||||
categories={product.techStack}
|
||||
/>
|
||||
)}
|
||||
<DataProofSection
|
||||
title="可衡量的成果"
|
||||
subtitle="用数据说话,每一项指标都源自真实客户案例"
|
||||
metrics={product.dataProofs.map((dp) => ({
|
||||
value: dp.value,
|
||||
label: dp.metric,
|
||||
description: dp.description,
|
||||
}))}
|
||||
/>
|
||||
{product.dataProofs && product.dataProofs.length > 0 && (
|
||||
<DataProofSection
|
||||
title="可衡量的成果"
|
||||
subtitle="用数据说话,每一项指标都源自真实客户案例"
|
||||
metrics={product.dataProofs.map((dp) => ({
|
||||
value: dp.value,
|
||||
label: dp.metric,
|
||||
description: dp.description,
|
||||
}))}
|
||||
/>
|
||||
)}
|
||||
<CaseStudiesSection caseStudies={product.caseStudies} />
|
||||
<CertificationsSection certifications={product.certifications} />
|
||||
{product.faqs && product.faqs.length > 0 && (
|
||||
|
||||
@@ -21,7 +21,8 @@ const PRODUCT_ICONS: Record<string, React.ReactNode> = {
|
||||
};
|
||||
|
||||
function useCountUp(target: number, start: boolean, duration: number = 2000) {
|
||||
const [count, setCount] = useState(0);
|
||||
// 初始值设为 target,避免动画触发前或用户偏好减少动效时显示 0
|
||||
const [count, setCount] = useState(target);
|
||||
const prefersReducedMotion = useReducedMotion();
|
||||
|
||||
useEffect(() => {
|
||||
@@ -162,7 +163,7 @@ function ProductCard({ product }: { product: Product }) {
|
||||
<div className="text-xs text-text-muted mb-1">{bundleLabel}</div>
|
||||
<h3 className="text-lg font-bold text-text-primary">{product.title}</h3>
|
||||
</div>
|
||||
<span className="px-2 py-1 text-xs bg-brand/10 text-brand">{bundleLabel}</span>
|
||||
<span className="px-2 py-1 text-xs bg-brand/10 text-brand" aria-hidden="true">{bundleLabel}</span>
|
||||
</div>
|
||||
|
||||
<p className="text-sm text-text-secondary mb-4 leading-relaxed flex-1">
|
||||
@@ -241,7 +242,7 @@ function BundleOverview({ products }: { products: Product[] }) {
|
||||
<Cpu className="w-5 h-5" />
|
||||
</div>
|
||||
<h3 className="text-xl font-bold text-ink">专业产品</h3>
|
||||
<span className="px-2 py-1 text-xs bg-accent-blue/10 text-accent-blue">独立部署</span>
|
||||
<span className="px-2 py-1 text-xs bg-accent-blue-soft text-text-primary">独立部署</span>
|
||||
</div>
|
||||
<p className="text-sm text-text-secondary leading-relaxed mb-6">
|
||||
聚焦特定领域的高复杂度需求,以独立产品形态提供专业能力,满足安全与合规的严苛要求。
|
||||
|
||||
Reference in New Issue
Block a user