fix(seo): 修复页面标题公司名重复与品牌名繁简体不一致问题
- 新增 COMPANY_INFO.displayName 属性用于页面标题和SEO元数据 - 统一所有页面 metadata 使用 displayName(简体"睿新致远") - 视觉展示元素保留 shortName(繁体"睿新致遠"配合青柳隷書字体) - 修复关于/联系/团队页面标题中公司名重复出现的问题 - 修复新闻ID从数字改为SEO友好slug - 更新结构化数据使用完整公司名 - 修复ESLint报错:引号转义、组件displayName、any类型替换
This commit is contained in:
@@ -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">我们不把“项目交付”当作终点。</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">这些问题,比“项目是否按时交付”更让我们在意。</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]">不做路过就忘的“一锤子买卖”</span>
|
||||
</li>
|
||||
</ul>
|
||||
<p className="text-[#1C1C1C] leading-relaxed font-medium">
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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}的品牌故事。我们不只是技术供应商,更是您数字化转型的成长伙伴。以智慧连接数字趋势,以伙伴身份陪您成长。`,
|
||||
};
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import { COMPANY_INFO } from '@/lib/constants';
|
||||
|
||||
export const metadata = {
|
||||
title: '联系我们 - 四川睿新致远科技有限公司',
|
||||
title: `联系我们 - ${COMPANY_INFO.displayName}`,
|
||||
description: '无论您有任何问题或合作意向,我们都很乐意与您交流',
|
||||
};
|
||||
|
||||
|
||||
@@ -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,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,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>
|
||||
|
||||
@@ -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,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 }) {
|
||||
|
||||
@@ -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,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,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,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
import { Metadata } from 'next';
|
||||
|
||||
import { COMPANY_INFO } from '@/lib/constants';
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: '解决方案 - 睿新致远',
|
||||
title: `解决方案 - ${COMPANY_INFO.displayName}`,
|
||||
description: '三种角色,一种身份——您的成长伙伴',
|
||||
};
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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}的核心团队。我们的团队成员拥有丰富的行业经验和技术专长,致力于为客户提供专业的数字化转型服务。`,
|
||||
};
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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() {
|
||||
|
||||
Reference in New Issue
Block a user