fix(seo): 修复页面标题公司名重复与品牌名繁简体不一致问题

- 新增 COMPANY_INFO.displayName 属性用于页面标题和SEO元数据
- 统一所有页面 metadata 使用 displayName(简体"睿新致远")
- 视觉展示元素保留 shortName(繁体"睿新致遠"配合青柳隷書字体)
- 修复关于/联系/团队页面标题中公司名重复出现的问题
- 修复新闻ID从数字改为SEO友好slug
- 更新结构化数据使用完整公司名
- 修复ESLint报错:引号转义、组件displayName、any类型替换
This commit is contained in:
张翔
2026-05-03 09:15:14 +08:00
parent f0657ce9f4
commit 1bf22a8f95
29 changed files with 183 additions and 76 deletions
+4 -4
View File
@@ -73,7 +73,7 @@ export function AboutClient() {
transition={{ duration: 0.5 }}
className="p-8 rounded-xl border border-[#E5E5E5]"
>
<h2 className="text-2xl font-bold text-[#1C1C1C] mb-6"> </h2>
<h2 className="text-2xl font-bold text-[#1C1C1C] mb-6"> {COMPANY_INFO.shortName}</h2>
<p className="text-xl font-semibold text-[#1C1C1C] mb-4"></p>
<p className="text-[#595959] mb-6 leading-relaxed"></p>
@@ -86,10 +86,10 @@ export function AboutClient() {
<div>
<h3 className="text-lg font-semibold text-[#1C1C1C] mb-3"></h3>
<p className="text-[#595959] mb-2 leading-relaxed">"项目交付"</p>
<p className="text-[#595959] mb-2 leading-relaxed">&ldquo;&rdquo;</p>
<p className="text-[#595959] mb-2 leading-relaxed"></p>
<p className="text-[#595959] mb-2 leading-relaxed"></p>
<p className="text-[#595959] mt-3 leading-relaxed">"项目是否按时交付"</p>
<p className="text-[#595959] mt-3 leading-relaxed">&ldquo;&rdquo;</p>
</div>
</motion.div>
@@ -113,7 +113,7 @@ export function AboutClient() {
</li>
<li className="flex items-start gap-3">
<span className="text-[#C41E3A] font-bold"></span>
<span className="text-[#595959]">"一锤子买卖"</span>
<span className="text-[#595959]">&ldquo;&rdquo;</span>
</li>
</ul>
<p className="text-[#1C1C1C] leading-relaxed font-medium">
+31 -21
View File
@@ -2,40 +2,42 @@ import { describe, it, expect, jest } from '@jest/globals';
import { render, screen } from '@testing-library/react';
import '@testing-library/jest-dom';
type MotionProps = { children: React.ReactNode; className?: string; [key: string]: unknown };
jest.mock('framer-motion', () => ({
motion: {
div: ({ children, className, ...props }: any) => (
div: ({ children, className, ...props }: MotionProps) => (
<div className={className} {...props}>
{children}
</div>
),
section: ({ children, className, ...props }: any) => (
section: ({ children, className, ...props }: MotionProps) => (
<section className={className} {...props}>
{children}
</section>
),
span: ({ children, className, ...props }: any) => (
span: ({ children, className, ...props }: MotionProps) => (
<span className={className} {...props}>
{children}
</span>
),
h1: ({ children, className, ...props }: any) => (
h1: ({ children, className, ...props }: MotionProps) => (
<h1 className={className} {...props}>
{children}
</h1>
),
h2: ({ children, className, ...props }: any) => (
h2: ({ children, className, ...props }: MotionProps) => (
<h2 className={className} {...props}>
{children}
</h2>
),
},
AnimatePresence: ({ children }: any) => <>{children}</>,
AnimatePresence: ({ children }: { children: React.ReactNode }) => <>{children}</>,
useInView: () => [null, true],
}));
jest.mock('next/link', () => {
const MockLink = ({ children, href, ...props }: any) => (
const MockLink = ({ children, href, ...props }: { children: React.ReactNode; href: string; [key: string]: unknown }) => (
<a href={href} {...props}>
{children}
</a>
@@ -54,40 +56,48 @@ jest.mock('lucide-react', () => ({
Phone: () => <span data-testid="phone-icon" />,
}));
jest.mock('@/components/ui/card', () => ({
Card: ({ children, className, ...props }: any) => (
jest.mock('@/components/ui/card', () => {
const Card = ({ children, className, ...props }: { children: React.ReactNode; className?: string; [key: string]: unknown }) => (
<div className={className} {...props}>
{children}
</div>
),
CardContent: ({ children, className, ...props }: any) => (
);
const CardContent = ({ children, className, ...props }: { children: React.ReactNode; className?: string; [key: string]: unknown }) => (
<div className={className} {...props}>
{children}
</div>
),
}));
);
Card.displayName = 'Card';
CardContent.displayName = 'CardContent';
return { Card, CardContent };
});
jest.mock('@/components/ui/page-header', () => ({
PageHeader: ({ title, description }: any) => (
jest.mock('@/components/ui/page-header', () => {
const PageHeader = ({ title, description }: { title: string; description?: string }) => (
<header>
<h1>{title}</h1>
<p>{description}</p>
</header>
),
}));
);
PageHeader.displayName = 'PageHeader';
return { PageHeader };
});
jest.mock('@/components/ui/flip-clock', () => ({
FlipClock: ({ years, months, days }: any) => (
jest.mock('@/components/ui/flip-clock', () => {
const FlipClock = ({ years, months, days }: { years: number; months: number; days: number }) => (
<div data-testid="flip-clock">
{years} {months} {days}
</div>
),
}));
);
FlipClock.displayName = 'FlipClock';
return { FlipClock };
});
jest.mock('@/lib/constants', () => ({
COMPANY_INFO: {
name: '四川睿新致远科技有限公司',
shortName: '睿新致遠',
displayName: '睿新致远',
description: '以智慧连接数字趋势,以伙伴身份陪您成长',
address: '四川省成都市龙泉驿区',
email: 'contact@ruixin.com',
+1 -1
View File
@@ -2,7 +2,7 @@ import { COMPANY_INFO } from '@/lib/constants';
import { AboutClient } from './client';
export const metadata = {
title: `关于我们 - ${COMPANY_INFO.name}`,
title: `关于我们 - ${COMPANY_INFO.displayName}`,
description: `了解${COMPANY_INFO.name}的品牌故事。我们不只是技术供应商,更是您数字化转型的成长伙伴。以智慧连接数字趋势,以伙伴身份陪您成长。`,
};
+3 -1
View File
@@ -1,5 +1,7 @@
import { COMPANY_INFO } from '@/lib/constants';
export const metadata = {
title: '联系我们 - 四川睿新致远科技有限公司',
title: `联系我们 - ${COMPANY_INFO.displayName}`,
description: '无论您有任何问题或合作意向,我们都很乐意与您交流',
};
+2 -2
View File
@@ -1,5 +1,5 @@
import { notFound } from 'next/navigation';
import { NEWS } from '@/lib/constants';
import { NEWS, COMPANY_INFO } from '@/lib/constants';
import { NewsDetailClient } from './NewsDetailClient';
export async function generateStaticParams() {
@@ -19,7 +19,7 @@ export async function generateMetadata({ params }: { params: Promise<{ slug: str
}
return {
title: `${news.title} - 睿新致远`,
title: `${news.title} - ${COMPANY_INFO.displayName}`,
description: news.excerpt,
};
}
+2 -2
View File
@@ -2,8 +2,8 @@ import { Metadata } from 'next';
import { COMPANY_INFO } from '@/lib/constants';
export const metadata: Metadata = {
title: `新闻动态 - ${COMPANY_INFO.shortName}`,
description: `了解${COMPANY_INFO.shortName}最新动态,把握行业发展脉搏。`,
title: `新闻动态 - ${COMPANY_INFO.displayName}`,
description: `了解${COMPANY_INFO.displayName}最新动态,把握行业发展脉搏。`,
};
export default function NewsLayout({ children }: { children: React.ReactNode }) {
+2 -2
View File
@@ -2,7 +2,7 @@
import { useState, useMemo, ChangeEvent } from 'react';
import { motion } from 'framer-motion';
import { NEWS } from '@/lib/constants';
import { NEWS, COMPANY_INFO } from '@/lib/constants';
import { Badge } from '@/components/ui/badge';
import { Input } from '@/components/ui/input';
import { Button } from '@/components/ui/button';
@@ -65,7 +65,7 @@ export default function NewsListPage() {
</h1>
<p className="text-lg text-[#595959] leading-relaxed">
{COMPANY_INFO.displayName}
</p>
</motion.div>
</div>
+2 -2
View File
@@ -1,6 +1,6 @@
import { notFound } from 'next/navigation';
import { StaticLink } from '@/components/ui/static-link';
import { PRODUCTS } from '@/lib/constants';
import { PRODUCTS, COMPANY_INFO } from '@/lib/constants';
import { Button } from '@/components/ui/button';
import { PageNav } from '@/components/layout/page-nav';
import { CheckCircle2, Zap, Target, Layers, ArrowRight } from 'lucide-react';
@@ -20,7 +20,7 @@ export async function generateMetadata({ params }: { params: Promise<{ id: strin
}
return {
title: `${product.title} - 睿新致远`,
title: `${product.title} - ${COMPANY_INFO.displayName}`,
description: product.description,
};
}
+2 -2
View File
@@ -2,8 +2,8 @@ import { Metadata } from 'next';
import { COMPANY_INFO } from '@/lib/constants';
export const metadata: Metadata = {
title: `产品 - ${COMPANY_INFO.shortName}`,
description: `自主研发的企业级产品,助力企业高效运营,实现数字化转型。${COMPANY_INFO.shortName}提供ERP、CRM、BI、CMS等产品。`,
title: `产品 - ${COMPANY_INFO.displayName}`,
description: `自主研发的企业级产品,助力企业高效运营,实现数字化转型。${COMPANY_INFO.displayName}提供ERP、CRM、BI、CMS等产品。`,
};
export default function ProductsLayout({ children }: { children: React.ReactNode }) {
+2 -2
View File
@@ -1,6 +1,6 @@
import { Metadata } from 'next';
import { notFound } from 'next/navigation';
import { SERVICES } from '@/lib/constants';
import { SERVICES, COMPANY_INFO } from '@/lib/constants';
import { ServiceDetailClient } from './client';
export async function generateStaticParams() {
@@ -20,7 +20,7 @@ export async function generateMetadata({ params }: { params: Promise<{ id: strin
}
return {
title: `${service.title} - 睿新致远`,
title: `${service.title} - ${COMPANY_INFO.displayName}`,
description: service.description,
};
}
+2 -2
View File
@@ -2,8 +2,8 @@ import { Metadata } from 'next';
import { COMPANY_INFO } from '@/lib/constants';
export const metadata: Metadata = {
title: `服务 - ${COMPANY_INFO.shortName}`,
description: `专业技术团队,为您提供全方位的数字化解决方案。${COMPANY_INFO.shortName}涵盖软件开发、数据分析、咨询服务等核心业务。`,
title: `服务 - ${COMPANY_INFO.displayName}`,
description: `专业技术团队,为您提供全方位的数字化解决方案。${COMPANY_INFO.displayName}涵盖软件开发、数据分析、咨询服务等核心业务。`,
};
export default function ServicesLayout({ children }: { children: React.ReactNode }) {
+2 -1
View File
@@ -2,6 +2,7 @@ import { Metadata } from 'next';
import { notFound } from 'next/navigation';
import { SOLUTIONS } from '@/lib/constants/solutions';
import { PRODUCTS } from '@/lib/constants/products';
import { COMPANY_INFO } from '@/lib/constants';
import { SolutionDetailClient } from './client';
export async function generateStaticParams() {
@@ -19,7 +20,7 @@ export async function generateMetadata({ params }: { params: Promise<{ id: strin
}
return {
title: `${solution.title} - 睿新致远`,
title: `${solution.title} - ${COMPANY_INFO.displayName}`,
description: solution.description,
};
}
+3 -1
View File
@@ -1,7 +1,9 @@
import { Metadata } from 'next';
import { COMPANY_INFO } from '@/lib/constants';
export const metadata: Metadata = {
title: '解决方案 - 睿新致远',
title: `解决方案 - ${COMPANY_INFO.displayName}`,
description: '三种角色,一种身份——您的成长伙伴',
};
+4 -1
View File
@@ -20,6 +20,7 @@ const modules = [
values: ['行业趋势洞察报告', '数字化转型成熟度评估', '个性化实施路径规划'],
cta: '预约一次免费诊断',
ctaVariant: 'default' as const,
ctaHref: '/contact',
},
{
icon: Cpu,
@@ -33,6 +34,7 @@ const modules = [
values: ['业务场景深度调研', '技术方案定制开发', '敏捷交付快速迭代'],
cta: '了解技术方案',
ctaVariant: 'outline' as const,
ctaHref: '/products',
},
{
icon: Users,
@@ -46,6 +48,7 @@ const modules = [
values: ['专属客户成功经理', '季度业务复盘会', '7×24小时响应通道'],
cta: '了解陪跑服务',
ctaVariant: 'default' as const,
ctaHref: '/services',
},
];
@@ -127,7 +130,7 @@ export default function SolutionsPage() {
className={module.ctaVariant === 'default' ? 'bg-[#C41E3A] hover:bg-[#A01830] text-white' : 'border-[#C41E3A] text-[#C41E3A] hover:bg-[#C41E3A] hover:text-white'}
asChild
>
<StaticLink href="/contact">
<StaticLink href={module.ctaHref}>
{module.cta}
<ArrowRight className="ml-2 w-4 h-4" />
</StaticLink>
+1 -1
View File
@@ -2,7 +2,7 @@ import { COMPANY_INFO } from '@/lib/constants';
import { TeamClient } from './client';
export const metadata = {
title: `核心团队 - ${COMPANY_INFO.name}`,
title: `核心团队 - ${COMPANY_INFO.displayName}`,
description: `了解${COMPANY_INFO.name}的核心团队。我们的团队成员拥有丰富的行业经验和技术专长,致力于为客户提供专业的数字化转型服务。`,
};
+2 -1
View File
@@ -3,6 +3,7 @@
import { StaticLink } from '@/components/ui/static-link';
import { Button } from '@/components/ui/button';
import { Home, ArrowLeft, Search } from 'lucide-react';
import { COMPANY_INFO } from '@/lib/constants';
export default function NotFound() {
return (
@@ -62,7 +63,7 @@ export default function NotFound() {
</div>
<div className="text-left">
<div className="font-semibold text-[#1C1C1C]"></div>
<div className="text-sm text-[#5C5C5C]"></div>
<div className="text-sm text-[#5C5C5C]">{COMPANY_INFO.displayName}</div>
</div>
</StaticLink>
+3 -2
View File
@@ -1,8 +1,9 @@
import { Metadata } from 'next';
import { COMPANY_INFO } from '@/lib/constants';
export const metadata: Metadata = {
title: '隐私政策 - 睿新致远',
description: '四川睿新致远科技有限公司隐私政策',
title: `隐私政策 - ${COMPANY_INFO.displayName}`,
description: `${COMPANY_INFO.name}隐私政策`,
};
export default function PrivacyPolicyPage() {
+3 -2
View File
@@ -1,8 +1,9 @@
import { Metadata } from 'next';
import { COMPANY_INFO } from '@/lib/constants';
export const metadata: Metadata = {
title: '服务条款 - 睿新致远',
description: '四川睿新致远科技有限公司服务条款',
title: `服务条款 - ${COMPANY_INFO.displayName}`,
description: `${COMPANY_INFO.name}服务条款`,
};
export default function TermsOfServicePage() {