diff --git a/src/app/(marketing)/about/brand/brand-content.tsx b/src/app/(marketing)/about/brand/brand-content.tsx index 146b470..09d6fcb 100644 --- a/src/app/(marketing)/about/brand/brand-content.tsx +++ b/src/app/(marketing)/about/brand/brand-content.tsx @@ -2,6 +2,7 @@ import { motion } from 'framer-motion'; import { ScrollReveal } from '@/components/ui/scroll-reveal'; +import { StaticLink } from '@/components/ui/static-link'; import { BrandCalligraphyName } from '@/components/ui/brand-calligraphy-name'; import { ArrowRight, @@ -355,20 +356,20 @@ export default function BrandContent() { 从一次深入的业务诊断开始,开启您的数据驱动之旅。

- 预约咨询 - - + 查看客户案例 - +
diff --git a/src/app/(marketing)/cases/cases-content-v3.tsx b/src/app/(marketing)/cases/cases-content-v3.tsx index bf08128..7a4d084 100644 --- a/src/app/(marketing)/cases/cases-content-v3.tsx +++ b/src/app/(marketing)/cases/cases-content-v3.tsx @@ -2,6 +2,7 @@ import { useState, useMemo } from 'react'; import { motion } from 'framer-motion'; +import { StaticLink } from '@/components/ui/static-link'; import { Building2, ArrowUpRight, Target, Lightbulb, Filter } from 'lucide-react'; import { type CaseStudy, @@ -308,19 +309,19 @@ export default function CasesContentV3({ 让我们聊聊您的挑战,看看能创造什么样的成果。

- 预约咨询 - - + 了解服务 - +
diff --git a/src/app/(marketing)/home-content-v14.tsx b/src/app/(marketing)/home-content-v14.tsx index 38f2471..9852b81 100644 --- a/src/app/(marketing)/home-content-v14.tsx +++ b/src/app/(marketing)/home-content-v14.tsx @@ -5,6 +5,7 @@ import Image from 'next/image'; import { motion } from 'framer-motion'; import { ScrollReveal, StaggerReveal } from '@/components/ui/scroll-reveal'; import { Badge } from '@/components/ui/badge'; +import { StaticLink } from '@/components/ui/static-link'; import { HeroProductVisual } from '@/components/sections/hero-product-visual'; import { ArrowRight, Lightbulb, Database, Layers, Code, Puzzle, Server } from 'lucide-react'; import { cn } from '@/lib/utils'; @@ -335,13 +336,13 @@ function TrustSection({ pageCopy }: { pageCopy?: HomePageCopy | null }) { ))} - {earlyCtaLabel} - + @@ -398,7 +399,10 @@ function NarrativeSection({ pageCopy }: { pageCopy?: HomePageCopy | null }) {
- +
@@ -524,13 +528,13 @@ function CasesSection({ cases, pageCopy }: { cases?: Record[]; page

{casesDesc}

- 成为首批共创客户 - +
@@ -556,13 +560,13 @@ function CasesSection({ cases, pageCopy }: { cases?: Record[]; page - 查看全部案例 - +
diff --git a/src/app/(marketing)/methodology/methodology-content.tsx b/src/app/(marketing)/methodology/methodology-content.tsx index 036a88a..6cd090a 100644 --- a/src/app/(marketing)/methodology/methodology-content.tsx +++ b/src/app/(marketing)/methodology/methodology-content.tsx @@ -2,6 +2,7 @@ import { motion } from 'framer-motion'; import { ScrollReveal, StaggerReveal } from '@/components/ui/scroll-reveal'; +import { StaticLink } from '@/components/ui/static-link'; import { EASE_OUT } from '@/components/ui/page-decoration'; import { Button } from '@/components/ui/button'; import { ArrowRight, CheckCircle2 } from 'lucide-react'; @@ -154,13 +155,13 @@ export function MethodologyContent({ data }: MethodologyContentProps) {

diff --git a/src/app/(marketing)/news/news-content-v3.tsx b/src/app/(marketing)/news/news-content-v3.tsx index 9c389c3..94b7598 100644 --- a/src/app/(marketing)/news/news-content-v3.tsx +++ b/src/app/(marketing)/news/news-content-v3.tsx @@ -75,7 +75,7 @@ function NewsCard({ newsItem, index }: { newsItem: NewsItem; index: number }) { } export default function NewsContentV3({ news, pageCopy }: { news?: NewsItem[]; pageCopy?: Record | null }) { - const NEWS = news ?? []; + const NEWS = useMemo(() => news ?? [], [news]); const [selectedCategory, setSelectedCategory] = useState('全部'); const [searchQuery, setSearchQuery] = useState(''); const [currentPage, setCurrentPage] = useState(1); @@ -94,7 +94,7 @@ export default function NewsContentV3({ news, pageCopy }: { news?: NewsItem[]; p newsItem.excerpt.toLowerCase().includes(searchQuery.toLowerCase()); return matchesCategory && matchesSearch; }); - }, [selectedCategory, searchQuery]); + }, [selectedCategory, searchQuery, NEWS]); const totalPages = Math.ceil(filteredNews.length / ITEMS_PER_PAGE); const paginatedNews = useMemo(() => { diff --git a/src/app/(marketing)/news/news-detail-content-v3.tsx b/src/app/(marketing)/news/news-detail-content-v3.tsx index 08462dd..ab855d0 100644 --- a/src/app/(marketing)/news/news-detail-content-v3.tsx +++ b/src/app/(marketing)/news/news-detail-content-v3.tsx @@ -1,6 +1,7 @@ 'use client'; import { ScrollReveal } from '@/components/ui/scroll-reveal'; +import { StaticLink } from '@/components/ui/static-link'; import { Badge } from '@/components/ui/badge'; import { Calendar, ArrowLeft, Newspaper, ArrowRight } from 'lucide-react'; import { SectionLabel, EASE_OUT } from '@/components/ui/page-decoration'; @@ -63,9 +64,9 @@ export default function NewsDetailContentV3({ news, relatedNews = [] }: NewsDeta
@@ -145,20 +146,20 @@ export default function NewsDetailContentV3({ news, relatedNews = [] }: NewsDeta {/* Navigation */}
diff --git a/src/app/(marketing)/products/erp-upgrade/erp-upgrade-content-v2.tsx b/src/app/(marketing)/products/erp-upgrade/erp-upgrade-content-v2.tsx index 35d2d75..d6c7c16 100644 --- a/src/app/(marketing)/products/erp-upgrade/erp-upgrade-content-v2.tsx +++ b/src/app/(marketing)/products/erp-upgrade/erp-upgrade-content-v2.tsx @@ -1,6 +1,7 @@ 'use client'; import { ScrollReveal, StaggerReveal } from '@/components/ui/scroll-reveal'; +import { StaticLink } from '@/components/ui/static-link'; import { Button } from '@/components/ui/button'; import { Badge } from '@/components/ui/badge'; import { @@ -153,10 +154,10 @@ export default function ErpUpgradeContentV2({ item }: ErpUpgradeContentV2Props)
diff --git a/src/app/(marketing)/products/product-detail-content-v3.tsx b/src/app/(marketing)/products/product-detail-content-v3.tsx index 851eb0c..e268df7 100644 --- a/src/app/(marketing)/products/product-detail-content-v3.tsx +++ b/src/app/(marketing)/products/product-detail-content-v3.tsx @@ -2,6 +2,7 @@ import { motion } from 'framer-motion'; import { ScrollReveal, StaggerReveal } from '@/components/ui/scroll-reveal'; +import { StaticLink } from '@/components/ui/static-link'; import { Button } from '@/components/ui/button'; import { ArrowRight, Package, Check, Settings, Users, FileText, Cpu, Shield, TrendingUp } from 'lucide-react'; import { SectionLabel, EASE_OUT } from '@/components/ui/page-decoration'; @@ -89,13 +90,13 @@ function DetailHero({ product }: DetailHeroProps) { className="flex flex-wrap gap-6" >
@@ -403,15 +404,29 @@ function CTASection({ product }: CTASectionProps) {
+ + {/* 站内入口:ERP 升级专题(与 erp-upgrade-content-v2 的反向链接形成互链闭环) */} + {product.id === 'erp' && ( +
+ 正在使用旧版 ERP? + + 了解睿新 ERP 升级专题 + + +
+ )} diff --git a/src/app/(marketing)/products/products-content-v3.tsx b/src/app/(marketing)/products/products-content-v3.tsx index af8b903..779145e 100644 --- a/src/app/(marketing)/products/products-content-v3.tsx +++ b/src/app/(marketing)/products/products-content-v3.tsx @@ -136,13 +136,13 @@ function HeroSection({ pageCopy }: { pageCopy?: PageCopy | null }) { className="flex flex-wrap gap-6" > @@ -425,7 +425,7 @@ function SuiteCombosSection({ products }: { products: Product[] }) { .filter(Boolean); return ( - - + ); })}
@@ -498,13 +498,13 @@ function CTASection({ pageCopy }: { pageCopy?: PageCopy | null }) {
diff --git a/src/app/(marketing)/products/standalone/[id]/client.tsx b/src/app/(marketing)/products/standalone/[id]/client.tsx index 68eed94..44a23cb 100644 --- a/src/app/(marketing)/products/standalone/[id]/client.tsx +++ b/src/app/(marketing)/products/standalone/[id]/client.tsx @@ -1,6 +1,7 @@ 'use client'; import { getHeroTheme } from '@/lib/constants/hero-themes'; +import { StaticLink } from '@/components/ui/static-link'; import { DetailHero } from '@/components/detail/detail-hero'; import { DetailTrustSection } from '@/components/detail/detail-trust-section'; import { DetailCTASection } from '@/components/detail/detail-cta-section'; @@ -112,19 +113,19 @@ export function StandaloneProductClient({ item }: StandaloneProductClientProps) )}
- 获取上线通知 - - + 查看其他产品 - +
diff --git a/src/app/(marketing)/services/service-detail-content-v4.tsx b/src/app/(marketing)/services/service-detail-content-v4.tsx index 96a7516..843f58e 100644 --- a/src/app/(marketing)/services/service-detail-content-v4.tsx +++ b/src/app/(marketing)/services/service-detail-content-v4.tsx @@ -1,6 +1,7 @@ 'use client'; import { motion } from 'framer-motion'; +import { StaticLink } from '@/components/ui/static-link'; import { ArrowUpRight, CheckCircle2, Zap, Clock, Users, Award, TrendingUp, Shield } from 'lucide-react'; import type { LucideIcon } from 'lucide-react'; import type { Service, CaseStudy } from '@/lib/constants/services'; @@ -80,13 +81,13 @@ function DetailHero({ service }: { service: Service }) { transition={{ duration: 0.8, delay: 0.9, ease: EASE_OUT }} className="flex flex-col sm:flex-row gap-4 sm:gap-6" > - 免费咨询 - +
- 预约免费咨询 - - + 返回服务列表 - +
diff --git a/src/app/(marketing)/services/services-content-v3.tsx b/src/app/(marketing)/services/services-content-v3.tsx index 0f4e83c..4f551f0 100644 --- a/src/app/(marketing)/services/services-content-v3.tsx +++ b/src/app/(marketing)/services/services-content-v3.tsx @@ -126,19 +126,19 @@ function HeroSection({ pageCopy }: { pageCopy?: PageCopy | null }) { transition={{ duration: 0.8, delay: 0.7, ease: EASE_OUT }} className="flex flex-col sm:flex-row gap-4 sm:gap-6" > - {ctaPrimary} - - + {ctaSecondary} - +
- 预约免费咨询 - - + 了解我们的团队 - +
diff --git a/src/app/(marketing)/solutions/solution-detail-content-v3.tsx b/src/app/(marketing)/solutions/solution-detail-content-v3.tsx index 9b6f0b1..061cd90 100644 --- a/src/app/(marketing)/solutions/solution-detail-content-v3.tsx +++ b/src/app/(marketing)/solutions/solution-detail-content-v3.tsx @@ -2,6 +2,7 @@ import { motion } from 'framer-motion'; import { ScrollReveal, StaggerReveal } from '@/components/ui/scroll-reveal'; +import { StaticLink } from '@/components/ui/static-link'; import { Button } from '@/components/ui/button'; import { ArrowRight, Factory, ShoppingCart, Heart, GraduationCap, Lightbulb, Settings, Users, TrendingUp, Package, BookOpen, MessageSquare, Calendar, Smartphone, Route, Shield, Truck } from 'lucide-react';import { SectionLabel, EASE_OUT } from '@/components/ui/page-decoration'; import type { Solution } from '@/lib/constants/solutions'; @@ -83,13 +84,13 @@ function DetailHero({ solution }: DetailHeroProps) { className="flex flex-wrap gap-6" > @@ -491,13 +492,13 @@ function CTASection({ solution }: CTASectionProps) {
diff --git a/src/app/(marketing)/solutions/solutions-content-v3.tsx b/src/app/(marketing)/solutions/solutions-content-v3.tsx index f9e5320..fd81366 100644 --- a/src/app/(marketing)/solutions/solutions-content-v3.tsx +++ b/src/app/(marketing)/solutions/solutions-content-v3.tsx @@ -74,19 +74,19 @@ function HeroSection({ pageCopy }: { pageCopy?: PageCopy | null }) { transition={{ duration: 0.8, delay: 0.7, ease: EASE_OUT }} className="flex flex-col sm:flex-row gap-4 sm:gap-6" > - {ctaPrimary} - - + {ctaSecondary} - +
- 获取定制方案 - - + 浏览产品 - +
diff --git a/src/app/test-error-tracking/page-client.tsx b/src/app/test-error-tracking/page-client.tsx new file mode 100644 index 0000000..6678943 --- /dev/null +++ b/src/app/test-error-tracking/page-client.tsx @@ -0,0 +1,163 @@ +'use client'; + +import { useState } from 'react'; +import { trackError } from '@/lib/analytics'; + +export default function TestErrorTrackingClient() { + const [testResults, setTestResults] = useState([]); + + const addResult = (message: string) => { + setTestResults((prev) => [...prev, `[${new Date().toLocaleTimeString()}] ${message}`]); + }; + + const testJavaScriptError = () => { + try { + addResult('🧪 测试 1: 触发 JavaScript 运行时错误...'); + throw new Error('测试错误:这是一个故意的 JavaScript 错误'); + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + trackError('javascript_error', errorMessage, false, { + test_id: 'test_js_error', + filename: 'test-error-page.tsx', + lineno: 20, + }); + addResult('✅ JavaScript 错误已发送到 GA4'); + } + }; + + const testPromiseRejection = () => { + addResult('🧪 测试 2: 触发 Promise 未捕获异常...'); + Promise.reject(new Error('测试错误:Promise 故意拒绝')); + addResult('✅ Promise 异常已触发(由 GlobalErrorTracker 自动捕获)'); + }; + + const testReactError = () => { + addResult('🧪 测试 3: 触发 React 渲染错误...'); + trackError('react_error', '组件渲染失败:测试故意错误', true, { + component: 'TestComponent', + stack_trace: 'Error: 测试错误\n at TestComponent...', + }); + addResult('✅ React 错误已发送到 GA4(标记为 fatal)'); + }; + + const testNetworkError = () => { + addResult('🧪 测试 4: 模拟网络请求错误...'); + trackError('network_error', 'Failed to fetch: https://api.example.com/data', false, { + url: 'https://api.example.com/data', + status_code: 0, + request_method: 'GET', + }); + addResult('✅ 网络错误已发送到 GA4'); + }; + + const clearResults = () => { + setTestResults([]); + }; + + return ( +
+
+

+ 🧪 GA4 错误监控测试面板 +

+ +
+

+ 测试用例 +

+
+ + + + +
+ + +
+ + {testResults.length > 0 && ( +
+

+ 📋 测试日志 +

+
+ {testResults.map((result, index) => ( +
+ {result} +
+ ))} +
+
+ )} + +
+

+ 💡 如何验证错误是否成功发送到 GA4? +

+
    +
  1. 点击上面的测试按钮
  2. +
  3. + 打开{' '} + + Google Analytics 后台 + +
  4. +
  5. 导航到:报告 → 实时
  6. +
  7. 在事件搜索框输入 exception
  8. +
  9. 你应该能在 30 秒内看到错误事件出现!
  10. +
+
+ +
+

+ 🔧 开发者工具调试 +

+

+ 在开发模式下,打开浏览器控制台(F12),你会看到类似这样的日志: +

+
+{`[GA4] Error tracked: {
+  description: "[javascript_error] 测试错误:这是一个故意的 JavaScript 错误",
+  fatal: "false",
+  url: "http://localhost:3000/test-error-tracking",
+  timestamp: "2025-01-15T10:30:00.000Z",
+  test_id: "test_js_error",
+  filename: "test-error-page.tsx",
+  lineno: 20
+}`}
+          
+
+
+
+ ); +} diff --git a/src/app/test-error-tracking/page.tsx b/src/app/test-error-tracking/page.tsx index db3e204..1e83f67 100644 --- a/src/app/test-error-tracking/page.tsx +++ b/src/app/test-error-tracking/page.tsx @@ -1,163 +1,12 @@ -'use client'; +import { Metadata } from 'next'; +import TestErrorTrackingClient from './page-client'; -import { useState } from 'react'; -import { trackError } from '@/lib/analytics'; +// QA 内部测试页:禁止搜索引擎收录(robots.txt 未屏蔽,需 metadata 层 noindex) +export const metadata: Metadata = { + title: '错误监控测试面板(内部)', + robots: { index: false, follow: false }, +}; export default function TestErrorTrackingPage() { - const [testResults, setTestResults] = useState([]); - - const addResult = (message: string) => { - setTestResults((prev) => [...prev, `[${new Date().toLocaleTimeString()}] ${message}`]); - }; - - const testJavaScriptError = () => { - try { - addResult('🧪 测试 1: 触发 JavaScript 运行时错误...'); - throw new Error('测试错误:这是一个故意的 JavaScript 错误'); - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - trackError('javascript_error', errorMessage, false, { - test_id: 'test_js_error', - filename: 'test-error-page.tsx', - lineno: 20, - }); - addResult('✅ JavaScript 错误已发送到 GA4'); - } - }; - - const testPromiseRejection = () => { - addResult('🧪 测试 2: 触发 Promise 未捕获异常...'); - Promise.reject(new Error('测试错误:Promise 故意拒绝')); - addResult('✅ Promise 异常已触发(由 GlobalErrorTracker 自动捕获)'); - }; - - const testReactError = () => { - addResult('🧪 测试 3: 触发 React 渲染错误...'); - trackError('react_error', '组件渲染失败:测试故意错误', true, { - component: 'TestComponent', - stack_trace: 'Error: 测试错误\n at TestComponent...', - }); - addResult('✅ React 错误已发送到 GA4(标记为 fatal)'); - }; - - const testNetworkError = () => { - addResult('🧪 测试 4: 模拟网络请求错误...'); - trackError('network_error', 'Failed to fetch: https://api.example.com/data', false, { - url: 'https://api.example.com/data', - status_code: 0, - request_method: 'GET', - }); - addResult('✅ 网络错误已发送到 GA4'); - }; - - const clearResults = () => { - setTestResults([]); - }; - - return ( -
-
-

- 🧪 GA4 错误监控测试面板 -

- -
-

- 测试用例 -

-
- - - - -
- - -
- - {testResults.length > 0 && ( -
-

- 📋 测试日志 -

-
- {testResults.map((result, index) => ( -
- {result} -
- ))} -
-
- )} - -
-

- 💡 如何验证错误是否成功发送到 GA4? -

-
    -
  1. 点击上面的测试按钮
  2. -
  3. - 打开{' '} - - Google Analytics 后台 - -
  4. -
  5. 导航到:报告 → 实时
  6. -
  7. 在事件搜索框输入 exception
  8. -
  9. 你应该能在 30 秒内看到错误事件出现!
  10. -
-
- -
-

- 🔧 开发者工具调试 -

-

- 在开发模式下,打开浏览器控制台(F12),你会看到类似这样的日志: -

-
-{`[GA4] Error tracked: {
-  description: "[javascript_error] 测试错误:这是一个故意的 JavaScript 错误",
-  fatal: "false",
-  url: "http://localhost:3000/test-error-tracking",
-  timestamp: "2025-01-15T10:30:00.000Z",
-  test_id: "test_js_error",
-  filename: "test-error-page.tsx",
-  lineno: 20
-}`}
-          
-
-
-
- ); + return ; } diff --git a/src/components/detail/brand-elements.tsx b/src/components/detail/brand-elements.tsx deleted file mode 100644 index fa47403..0000000 --- a/src/components/detail/brand-elements.tsx +++ /dev/null @@ -1,145 +0,0 @@ -'use client'; - -import { motion } from 'framer-motion'; -import { type LucideIcon } from 'lucide-react'; -import type { ReactNode } from 'react'; - -interface BrandSealProps { - text?: string; - variant?: 'red' | 'gold' | 'blue'; - size?: 'sm' | 'md' | 'lg'; -} - -export function BrandSeal({ text = '旗舰', variant = 'red', size = 'md' }: BrandSealProps) { - const sizes = { - sm: 'w-14 h-14 text-xs', - md: 'w-20 h-20 text-sm', - lg: 'w-28 h-28 text-base', - }; - - const colors = { - red: { - border: '#C41E3A', - bg: 'rgba(196, 30, 58, 0.06)', - text: '#C41E3A', - shadow: 'rgba(196, 30, 58, 0.2)', - }, - gold: { - border: '#d97706', - bg: 'rgba(217, 119, 6, 0.06)', - text: '#d97706', - shadow: 'rgba(217, 119, 6, 0.2)', - }, - blue: { - border: '#2563eb', - bg: 'rgba(37, 99, 235, 0.06)', - text: '#2563eb', - shadow: 'rgba(37, 99, 235, 0.2)', - }, - }; - - const color = colors[variant]; - - return ( - -
- - {text} - -
- - ); -} - -interface CalligraphyTextProps { - children: ReactNode; - className?: string; - as?: 'h1' | 'h2' | 'h3' | 'span'; -} - -export function CalligraphyText({ - children, - className = '', - as: Tag = 'span', -}: CalligraphyTextProps) { - return ( - - {children} - - ); -} - -interface SectionHeaderProps { - badge?: string; - title: ReactNode; - subtitle?: string; - align?: 'left' | 'center'; - icon?: LucideIcon; -} - -export function SectionHeader({ - badge, - title, - subtitle, - align = 'center', - icon: Icon, -}: SectionHeaderProps) { - return ( - - {(badge || Icon) && ( -
- {Icon && } - {badge} -
- )} - -

- {title} -

- - {subtitle && ( -

{subtitle}

- )} -
- ); -} diff --git a/src/components/detail/detail-cross-recommend.tsx b/src/components/detail/detail-cross-recommend.tsx deleted file mode 100644 index 1e95874..0000000 --- a/src/components/detail/detail-cross-recommend.tsx +++ /dev/null @@ -1,106 +0,0 @@ -'use client'; - -import { motion } from 'framer-motion'; -import { ArrowRight, Package, Lightbulb, Wrench } from 'lucide-react'; -import type { CrossReference } from '@/lib/constants/cross-references'; - -interface CrossRecommendGridProps { - items: CrossReference[]; - title?: string; -} - -const typeConfig = { - product: { - icon: Package, - label: '产品', - color: '#3b82f6', - bg: '#eff6ff', - }, - solution: { - icon: Lightbulb, - label: '方案', - color: '#C41E3A', - bg: '#FEF2F4', - }, - service: { - icon: Wrench, - label: '服务', - color: '#7c3aed', - bg: '#f5f3ff', - }, -}; - -export function CrossRecommendGrid({ items, title = '相关推荐' }: CrossRecommendGridProps) { - if (items.length === 0) return null; - - return ( -
-
- -
-
- - {title} - -
-

- 探索更多可能 -

-

- 发现与您需求相关的产品、方案和服务 -

- - -
- {items.map((item, index) => { - const config = typeConfig[item.type]; - const Icon = config.icon; - - return ( - -
- -
-
-
- - {config.label} - - -
-

{item.title}

-

- {item.reason} -

-
-
- ); - })} -
-
-
- ); -} \ No newline at end of file diff --git a/src/components/detail/detail.test.tsx b/src/components/detail/detail.test.tsx index 4dacdf0..8aedbfa 100644 --- a/src/components/detail/detail.test.tsx +++ b/src/components/detail/detail.test.tsx @@ -261,12 +261,6 @@ const mockProduct = { ], }; -const mockCrossRefItems = [ - { id: 's1', title: '智能制造方案', type: 'solution' as const, href: '/solutions/s1', reason: 'ERP 是核心组件' }, - { id: 'p2', title: 'CRM 系统', type: 'product' as const, href: '/products/crm', reason: '常与 ERP 一起使用' }, - { id: 'sv1', title: '软件定制开发', type: 'service' as const, href: '/services/sv1', reason: '配套服务' }, -]; - // ─── Tests ─────────────────────────────────────────────────────────────── describe('DetailHero', () => { @@ -573,58 +567,4 @@ describe('DetailCTASection', () => { }); }); -describe('CrossRecommendGrid', () => { - it('should render nothing when items is empty', async () => { - const { CrossRecommendGrid } = await import('./detail-cross-recommend'); - const { container } = render(); - expect(container.innerHTML).toBe(''); - }); - - it('should render default title', async () => { - const { CrossRecommendGrid } = await import('./detail-cross-recommend'); - render(); - expect(screen.getByText('相关推荐')).toBeInTheDocument(); - }); - - it('should render custom title', async () => { - const { CrossRecommendGrid } = await import('./detail-cross-recommend'); - render(); - expect(screen.getByText('更多推荐')).toBeInTheDocument(); - }); - - it('should render all items', async () => { - const { CrossRecommendGrid } = await import('./detail-cross-recommend'); - render(); - expect(screen.getByText('智能制造方案')).toBeInTheDocument(); - expect(screen.getByText('CRM 系统')).toBeInTheDocument(); - expect(screen.getByText('软件定制开发')).toBeInTheDocument(); - }); - - it('should render reason for each item', async () => { - const { CrossRecommendGrid } = await import('./detail-cross-recommend'); - render(); - expect(screen.getByText('ERP 是核心组件')).toBeInTheDocument(); - expect(screen.getByText('常与 ERP 一起使用')).toBeInTheDocument(); - expect(screen.getByText('配套服务')).toBeInTheDocument(); - }); - - it('should render correct type labels', async () => { - const { CrossRecommendGrid } = await import('./detail-cross-recommend'); - render(); - // Type labels: product=产品, solution=方案, service=服务 - expect(screen.getByText('产品')).toBeInTheDocument(); - // There might be multiple "方案" texts in the page, so use getAllByText - const solutionLabels = screen.getAllByText('方案'); - expect(solutionLabels.length).toBeGreaterThanOrEqual(1); - expect(screen.getByText('服务')).toBeInTheDocument(); - }); - - it('should render links for items', async () => { - const { CrossRecommendGrid } = await import('./detail-cross-recommend'); - render(); - const solutionLink = screen.getByText('智能制造方案').closest('a'); - expect(solutionLink).toHaveAttribute('href', '/solutions/s1'); - const productLink = screen.getByText('CRM 系统').closest('a'); - expect(productLink).toHaveAttribute('href', '/products/crm'); - }); -}); \ No newline at end of file +// 注:CrossRecommendGrid 相关测试已随组件删除(2026-08-31,组件生产 0 引用) \ No newline at end of file diff --git a/src/components/detail/index.ts b/src/components/detail/index.ts index f4b6ff8..b41f0da 100644 --- a/src/components/detail/index.ts +++ b/src/components/detail/index.ts @@ -8,7 +8,6 @@ export { DetailCTASection } from './detail-cta-section'; export { CaseStudyCard } from './detail-case-study'; export { CertificationList } from './detail-certification'; -export { CrossRecommendGrid } from './detail-cross-recommend'; export { SolutionValueSection } from './solution-value'; export { ServiceValueSection } from './service-value'; @@ -19,4 +18,5 @@ export { SolutionCard } from './solution-service-card'; export { TiltCard, PressableButton, HoverLink } from './micro-interactions'; -export { BrandSeal, CalligraphyText, SectionHeader } from './brand-elements'; +// 注:brand-elements.tsx(BrandSeal/CalligraphyText/SectionHeader)与 +// detail-cross-recommend.tsx(CrossRecommendGrid)此前 0 消费者,已于 2026-08-31 删除。 diff --git a/src/components/detail/product-card.tsx b/src/components/detail/product-card.tsx index c059430..28483ae 100644 --- a/src/components/detail/product-card.tsx +++ b/src/components/detail/product-card.tsx @@ -36,6 +36,7 @@ export function ProductCard({ product }: ProductCardProps) { src={product.image} alt={product.title} fill + sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw" className="object-cover group-hover:scale-105 transition-transform duration-500" /> diff --git a/src/components/sections/case-card.tsx b/src/components/sections/case-card.tsx index 982a89b..41d1aab 100644 --- a/src/components/sections/case-card.tsx +++ b/src/components/sections/case-card.tsx @@ -48,14 +48,11 @@ export function CaseCard({ > {/* Background image */} {image && ( -
- -
+ - {tech.name} + {tech.name}
))}
diff --git a/src/components/ui/product-card.tsx b/src/components/ui/product-card.tsx index 69d38f9..e518b6c 100644 --- a/src/components/ui/product-card.tsx +++ b/src/components/ui/product-card.tsx @@ -35,8 +35,8 @@ const defaultConfig = { const statusConfig = { '研发中': { bg: 'rgba(var(--color-brand-rgb), 0.06)', text: 'var(--color-brand)', border: 'rgba(var(--color-brand-rgb), 0.12)' }, - '内测中': { bg: 'rgba(var(--color-warning-rgb), 0.06)', text: 'var(--color-warning)', border: 'rgba(var(--color-warning-rgb), 0.12)' }, - '已发布': { bg: 'rgba(var(--color-success-rgb), 0.06)', text: 'var(--color-success)', border: 'rgba(var(--color-success-rgb), 0.12)' }, + '内测中': { bg: 'rgba(var(--color-warning-rgb), 0.06)', text: 'var(--color-warning-text)', border: 'rgba(var(--color-warning-rgb), 0.12)' }, + '已发布': { bg: 'rgba(var(--color-success-rgb), 0.06)', text: 'var(--color-success-text)', border: 'rgba(var(--color-success-rgb), 0.12)' }, } as const; export function ProductCard({ title, description, href, index, status }: ProductCardProps) {