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() {
+30 -2
View File
@@ -1,6 +1,6 @@
'use client';
import { useState, useEffect, useCallback } from 'react';
import { useState, useEffect, useCallback, useRef } from 'react';
import {
updateConsentDetailed,
trackButtonClick,
@@ -13,19 +13,37 @@ import { motion, AnimatePresence } from 'framer-motion';
const LEGACY_CONSENT_KEY = 'ga_consent';
let hasConsentBeenHandled = false;
function getInitialShowConsent(): boolean {
if (typeof window === 'undefined') {return false;}
if (hasConsentBeenHandled) {return false;}
const stored = getStoredPreferences();
if (stored) {return false;}
const legacyConsent = localStorage.getItem(LEGACY_CONSENT_KEY);
if (legacyConsent) {return false;}
return false;
}
export function CookieConsent() {
const [showConsent, setShowConsent] = useState(false);
const [showConsent, setShowConsent] = useState(getInitialShowConsent);
const [showSettings, setShowSettings] = useState(false);
const [isAnimating, setIsAnimating] = useState(false);
const [preferences, setPreferences] = useState<CookiePreferences>(getDefaultPreferences());
const consentCheckedRef = useRef(false);
useEffect(() => {
if (consentCheckedRef.current) {return;}
consentCheckedRef.current = true;
const stored = getStoredPreferences();
if (stored) {
hasConsentBeenHandled = true;
updateConsentDetailed(stored);
} else {
const legacyConsent = localStorage.getItem(LEGACY_CONSENT_KEY);
if (legacyConsent) {
hasConsentBeenHandled = true;
const migratedPrefs: CookiePreferences = {
necessary: true,
analytics: legacyConsent === 'granted',
@@ -45,8 +63,18 @@ export function CookieConsent() {
return undefined;
}, []);
useEffect(() => {
const handleOpenSettings = () => {
setShowSettings(true);
setShowConsent(true);
};
window.addEventListener('open-cookie-settings', handleOpenSettings);
return () => window.removeEventListener('open-cookie-settings', handleOpenSettings);
}, []);
const handleSavePreferences = useCallback((prefs: CookiePreferences) => {
setIsAnimating(true);
hasConsentBeenHandled = true;
const finalPrefs = { ...prefs, timestamp: Date.now() };
storePreferences(finalPrefs);
updateConsentDetailed(finalPrefs);
+2
View File
@@ -35,6 +35,8 @@ jest.mock('lucide-react', () => ({
jest.mock('@/lib/constants', () => ({
COMPANY_INFO: {
name: '四川睿新致远科技有限公司',
shortName: '睿新致遠',
displayName: '睿新致远',
description: '以智慧连接数字趋势,以伙伴身份陪您成长',
email: 'contact@novalon.cn',
phone: '028-88888888',
+15 -8
View File
@@ -15,28 +15,32 @@ jest.mock('next/navigation', () => ({
}));
jest.mock('next/link', () => {
return ({ children, href, onClick, ...props }: any) => (
const MockLink = ({ children, href, onClick, ...props }: { children: React.ReactNode; href: string; onClick?: () => void; [key: string]: unknown }) => (
<a href={href} onClick={onClick} {...props}>
{children}
</a>
);
MockLink.displayName = 'MockLink';
return MockLink;
});
jest.mock('next/image', () => {
return ({ src, alt, width, height, className, ...props }: any) => (
const MockImage = ({ src, alt, width, height, className, ...props }: { src: string; alt: string; width: number; height: number; className?: string; [key: string]: unknown }) => (
<img src={src} alt={alt} width={width} height={height} className={className} {...props} />
);
MockImage.displayName = 'MockImage';
return MockImage;
});
jest.mock('framer-motion', () => ({
motion: {
div: ({ children, className, ...props }: any) => (
div: ({ children, className, ...props }: { children: React.ReactNode; className?: string; [key: string]: unknown }) => (
<div className={className} {...props}>
{children}
</div>
),
},
AnimatePresence: ({ children }: any) => <>{children}</>,
AnimatePresence: ({ children }: { children: React.ReactNode }) => <>{children}</>,
}));
jest.mock('lucide-react', () => ({
@@ -44,18 +48,21 @@ jest.mock('lucide-react', () => ({
X: () => <span data-testid="x-icon" />,
}));
jest.mock('@/components/ui/button', () => ({
Button: ({ children, className, asChild, ...props }: any) => (
jest.mock('@/components/ui/button', () => {
const MockButton = ({ children, className, ...props }: { children: React.ReactNode; className?: string; [key: string]: unknown }) => (
<button className={className} {...props}>
{children}
</button>
),
}));
);
MockButton.displayName = 'MockButton';
return { Button: MockButton };
});
jest.mock('@/lib/constants', () => ({
COMPANY_INFO: {
name: '四川睿新致远科技有限公司',
shortName: '睿新致遠',
displayName: '睿新致远',
},
NAVIGATION: [
{ id: 'home', label: '首页', href: '/' },
+6 -2
View File
@@ -108,7 +108,11 @@ function HeaderContent() {
label={item.label}
items={MEGA_DROPDOWN_DATA[item.dropdownKey!] ?? []}
isOpen={openDropdown === item.id}
onToggle={() => setOpenDropdown(openDropdown === item.id ? null : item.id)}
onToggle={() => {
setOpenDropdown((prev) => prev === item.id ? null : item.id);
}}
onOpen={() => setOpenDropdown(item.id)}
onClose={() => setOpenDropdown((prev) => prev === item.id ? null : prev)}
/>
) : (
<StaticLink
@@ -224,7 +228,7 @@ function HeaderContent() {
size="lg"
>
<StaticLink href="/contact" onClick={() => setIsOpen(false)}>
</StaticLink>
</Button>
</div>
+41 -2
View File
@@ -11,10 +11,15 @@ interface MegaDropdownProps {
items: MegaDropdownItem[];
isOpen: boolean;
onToggle: () => void;
onOpen?: () => void;
onClose?: () => void;
}
export function MegaDropdown({ label, items, isOpen, onToggle }: MegaDropdownProps) {
const HOVER_DELAY = 150;
export function MegaDropdown({ label, items, isOpen, onToggle, onOpen, onClose }: MegaDropdownProps) {
const dropdownRef = useRef<HTMLDivElement>(null);
const hoverTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);
useEffect(() => {
function handleClickOutside(event: MouseEvent) {
@@ -26,8 +31,42 @@ export function MegaDropdown({ label, items, isOpen, onToggle }: MegaDropdownPro
return () => document.removeEventListener('mousedown', handleClickOutside);
}, [isOpen, onToggle]);
useEffect(() => {
return () => {
if (hoverTimeoutRef.current) {
clearTimeout(hoverTimeoutRef.current);
}
};
}, []);
const handleMouseEnter = () => {
if (hoverTimeoutRef.current) {
clearTimeout(hoverTimeoutRef.current);
hoverTimeoutRef.current = null;
}
if (!isOpen) {
if (onOpen) {
onOpen();
} else {
onToggle();
}
}
};
const handleMouseLeave = () => {
hoverTimeoutRef.current = setTimeout(() => {
if (isOpen) {
if (onClose) {
onClose();
} else {
onToggle();
}
}
}, HOVER_DELAY);
};
return (
<div ref={dropdownRef} className="relative">
<div ref={dropdownRef} className="relative" onMouseEnter={handleMouseEnter} onMouseLeave={handleMouseLeave}>
<button
onClick={onToggle}
className={`
+2 -1
View File
@@ -4,6 +4,7 @@ import { motion } from 'framer-motion';
import { StaticLink } from '@/components/ui/static-link';
import { Button } from '@/components/ui/button';
import { ArrowRight } from 'lucide-react';
import { COMPANY_INFO } from '@/lib/constants';
interface CTASectionProps {
title?: string;
@@ -16,7 +17,7 @@ interface CTASectionProps {
export function CTASection({
title = '开启您的数字化转型之旅',
description = '与睿新致遠一起,让技术成为您业务增长的核心引擎',
description = `${COMPANY_INFO.shortName}一起,让技术成为您业务增长的核心引擎`,
primaryLabel = '立即咨询',
primaryHref = '/contact',
secondaryLabel = '了解方案',
+3 -2
View File
@@ -1,6 +1,7 @@
import { render } from '@testing-library/react';
import '@testing-library/jest-dom';
import { OrganizationSchema, WebsiteSchema } from './structured-data';
import { COMPANY_INFO } from '@/lib/constants';
describe('StructuredData', () => {
beforeEach(() => {
@@ -18,7 +19,7 @@ describe('StructuredData', () => {
const { container } = render(<OrganizationSchema />);
const script = container.querySelector('script[type="application/ld+json"]');
const schema = JSON.parse(script?.textContent || '{}');
expect(schema.name).toBe('四川睿新致远科技有限公司');
expect(schema.name).toBe(COMPANY_INFO.name);
});
it('should contain organization type', () => {
@@ -54,7 +55,7 @@ describe('StructuredData', () => {
const { container } = render(<WebsiteSchema />);
const script = container.querySelector('script[type="application/ld+json"]');
const schema = JSON.parse(script?.textContent || '{}');
expect(schema.name).toBe('四川睿新致远科技有限公司');
expect(schema.name).toBe(COMPANY_INFO.name);
});
});
});
+5 -3
View File
@@ -1,8 +1,10 @@
import { COMPANY_INFO } from '@/lib/constants';
export function OrganizationSchema() {
const schema = {
"@context": "https://schema.org",
"@type": "Organization",
"name": "四川睿新致远科技有限公司",
"name": COMPANY_INFO.name,
"alternateName": "诺瓦隆",
"url": "https://www.novalon.cn",
"logo": "https://www.novalon.cn/logo.svg",
@@ -32,7 +34,7 @@ export function WebsiteSchema() {
const schema = {
"@context": "https://schema.org",
"@type": "WebSite",
"name": "四川睿新致远科技有限公司",
"name": COMPANY_INFO.name,
"url": "https://www.novalon.cn",
"potentialAction": {
"@type": "SearchAction",
@@ -56,7 +58,7 @@ export function ServiceSchema() {
"serviceType": "企业数字化转型服务",
"provider": {
"@type": "Organization",
"name": "四川睿新致远科技有限公司"
"name": COMPANY_INFO.name
},
"description": "提供软件开发、云计算、数据分析、信息安全等一站式数字化转型解决方案",
"areaServed": {
+4 -3
View File
@@ -2,6 +2,7 @@
import { useRef, useState, useCallback, type ReactNode } from 'react';
import { motion } from 'framer-motion';
import { StaticLink } from '@/components/ui/static-link';
interface InkGlowCardProps {
children: ReactNode;
@@ -33,7 +34,7 @@ export function InkGlowCard({
const [isHovered, setIsHovered] = useState(false);
const handleMouseMove = useCallback((e: React.MouseEvent) => {
if (!cardRef.current) return;
if (!cardRef.current) {return;}
const rect = cardRef.current.getBoundingClientRect();
setMousePos({
x: e.clientX - rect.left,
@@ -72,7 +73,7 @@ export function InkGlowCard({
} as React.CSSProperties}
>
{href ? (
<a
<StaticLink
href={href}
className="relative block rounded-2xl bg-white overflow-hidden transition-all duration-500"
style={{
@@ -86,7 +87,7 @@ export function InkGlowCard({
onMouseLeave={() => setIsHovered(false)}
>
{content}
</a>
</StaticLink>
) : (
<div
className="relative rounded-2xl bg-white overflow-hidden transition-all duration-500"
+1
View File
@@ -1,6 +1,7 @@
export const COMPANY_INFO = {
name: '四川睿新致远科技有限公司',
shortName: '睿新致遠',
displayName: '睿新致远',
slogan: '智连未来,成长伙伴',
description: '以智慧连接数字趋势,以伙伴身份陪您成长——您的数字化转型同行者',
founded: '2026',
+2 -2
View File
@@ -12,7 +12,7 @@ export interface NewsItem {
export const NEWS: NewsItem[] = [
{
id: '1',
id: 'company-founded',
title: '四川睿新致远科技有限公司正式成立',
excerpt: '2026年1月15日,四川睿新致远科技有限公司在成都龙泉驿区正式成立,标志着公司在科技创新领域迈出了坚实的第一步。',
date: '2026-01-15',
@@ -27,7 +27,7 @@ export const NEWS: NewsItem[] = [
`,
},
{
id: '2',
id: 'digital-transformation-solution',
title: '公司推出企业数字化转型解决方案',
excerpt: '针对中小企业数字化转型需求,公司推出一站式数字化转型解决方案,帮助企业快速实现数字化升级。',
date: '2026-02-20',