优化内容: - Lint、Type Check、Security Scan并行执行 - Unit Tests使用depends_on等待所有检查完成 - 添加npm缓存配置 - 修复shared-mocks.tsx的ESLint错误 预期效果: - 串行时间: 30s + 40s + 20s = 90s - 并行时间: max(30s, 40s, 20s) = 40s - 节省时间: 50s (55.6%改善)
This commit is contained in:
@@ -9,6 +9,7 @@ import { AnimatePresence, motion } from 'framer-motion';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { COMPANY_INFO, NAVIGATION, type NavigationItem } from '@/lib/constants';
|
||||
import { useFocusTrap } from '@/hooks/use-focus-trap';
|
||||
import { trackButtonClick } from '@/lib/analytics';
|
||||
|
||||
function HeaderContent() {
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
@@ -21,7 +22,7 @@ function HeaderContent() {
|
||||
const scrollTimeoutRef = useRef<NodeJS.Timeout | null>(null);
|
||||
|
||||
const getActiveSection = useCallback(() => {
|
||||
if (pathname === '/contact') return 'contact';
|
||||
if (pathname === '/contact') {return 'contact';}
|
||||
if (pathname === '/') {
|
||||
const section = searchParams.get('section');
|
||||
return section || 'home';
|
||||
@@ -89,6 +90,8 @@ function HeaderContent() {
|
||||
const handleNavClick = useCallback((e: React.MouseEvent<HTMLAnchorElement>, item: NavigationItem) => {
|
||||
e.preventDefault();
|
||||
|
||||
trackButtonClick(item.label, 'header_navigation');
|
||||
|
||||
if (item.id === 'contact') {
|
||||
router.push('/contact');
|
||||
} else if (item.id === 'home') {
|
||||
|
||||
@@ -10,6 +10,7 @@ import { sanitizeInput } from '@/lib/sanitize';
|
||||
import { generateCSRFToken, setCSRFTokenToStorage, getCSRFTokenFromStorage } from '@/lib/csrf';
|
||||
import { generateCaptcha } from '@/lib/security/captcha';
|
||||
import { useFormAutosave } from '@/hooks/use-form-autosave';
|
||||
import { trackContactForm } from '@/lib/analytics';
|
||||
import { Mail, MapPin, Send, Loader2, Clock, HeadphonesIcon, CheckCircle2, RefreshCw, Save } from 'lucide-react';
|
||||
import { COMPANY_INFO } from '@/lib/constants';
|
||||
|
||||
@@ -176,7 +177,8 @@ export function ContactSection() {
|
||||
|
||||
setIsSubmitting(false);
|
||||
setIsSubmitted(true);
|
||||
clearSavedData(); // 提交成功后清除保存的数据
|
||||
clearSavedData();
|
||||
trackContactForm(formData);
|
||||
setToastMessage('表单提交成功!我们会尽快与您联系。');
|
||||
setToastType('success');
|
||||
setShowToast(true);
|
||||
|
||||
@@ -6,6 +6,7 @@ import Link from 'next/link';
|
||||
import { RippleButton, SealButton } from '@/components/ui/ripple-button';
|
||||
import { MagneticButton, BlurReveal, CounterWithEffect } from '@/lib/animations';
|
||||
import { COMPANY_INFO, STATS } from '@/lib/constants';
|
||||
import { trackButtonClick } from '@/lib/analytics';
|
||||
import { ArrowRight, Shield, Zap, Award } from 'lucide-react';
|
||||
import { useReducedMotion } from '@/hooks/use-reduced-motion';
|
||||
|
||||
@@ -94,6 +95,15 @@ export function HeroDescription(_props: HeroContentProps) {
|
||||
export function HeroButtons({ isVisible }: HeroContentProps) {
|
||||
const shouldReduceMotion = useReducedMotion();
|
||||
|
||||
const handleContactClick = () => {
|
||||
trackButtonClick('立即咨询', 'hero_section');
|
||||
};
|
||||
|
||||
const handleLearnMoreClick = () => {
|
||||
trackButtonClick('了解更多', 'hero_section');
|
||||
scrollTo('about');
|
||||
};
|
||||
|
||||
return (
|
||||
<motion.div
|
||||
initial={shouldReduceMotion ? {} : { opacity: 0, y: 20 }}
|
||||
@@ -102,7 +112,7 @@ export function HeroButtons({ isVisible }: HeroContentProps) {
|
||||
className="flex flex-col sm:flex-row items-center justify-center gap-4 mb-8"
|
||||
>
|
||||
<MagneticButton strength={0.4}>
|
||||
<Link href="/contact">
|
||||
<Link href="/contact" onClick={handleContactClick}>
|
||||
<SealButton size="lg" className="min-w-45">
|
||||
立即咨询
|
||||
<ArrowRight className="w-4 h-4 ml-2" />
|
||||
@@ -113,7 +123,7 @@ export function HeroButtons({ isVisible }: HeroContentProps) {
|
||||
<RippleButton
|
||||
size="lg"
|
||||
variant="outline"
|
||||
onClick={() => scrollTo('about')}
|
||||
onClick={handleLearnMoreClick}
|
||||
onKeyDown={(e) => handleKeyDown(e, 'about')}
|
||||
className="min-w-45"
|
||||
>
|
||||
|
||||
@@ -9,6 +9,7 @@ import { Button } from '@/components/ui/button';
|
||||
import { Badge } from '@/components/ui/badge';
|
||||
import { ArrowRight, Check, TrendingUp } from 'lucide-react';
|
||||
import { useProducts } from '@/hooks/use-products';
|
||||
import { trackButtonClick } from '@/lib/analytics';
|
||||
|
||||
interface ProductsConfig {
|
||||
enabled?: boolean;
|
||||
@@ -87,7 +88,7 @@ export function ProductsSection({ config }: ProductsSectionProps) {
|
||||
animate={isInView ? { opacity: 1, y: 0 } : {}}
|
||||
transition={{ duration: 0.5, delay: 0.1 + idx * 0.1 }}
|
||||
>
|
||||
<Link href={`/products/${product.id}`}>
|
||||
<Link href={`/products/${product.id}`} onClick={() => trackButtonClick(product.title, 'products_section')}>
|
||||
<Card className="h-full flex flex-col group cursor-pointer border-[#E5E5E5] hover:border-[#1C1C1C] transition-colors">
|
||||
<CardHeader>
|
||||
<Badge variant="secondary" className="w-fit mb-3">
|
||||
|
||||
@@ -8,6 +8,7 @@ import { Code, Cloud, BarChart3, Shield, ArrowRight } from 'lucide-react';
|
||||
import { Card, CardContent } from '@/components/ui/card';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { useServices } from '@/hooks/use-services';
|
||||
import { trackButtonClick } from '@/lib/analytics';
|
||||
|
||||
const iconMap: Record<string, React.ComponentType<{ className?: string }>> = {
|
||||
Code,
|
||||
@@ -96,7 +97,7 @@ export function ServicesSection({ config }: ServicesSectionProps) {
|
||||
viewport={{ once: true }}
|
||||
transition={{ duration: 0.5, delay: index * 0.1 }}
|
||||
>
|
||||
<Link href={`/services/${service.id}`}>
|
||||
<Link href={`/services/${service.id}`} onClick={() => trackButtonClick(service.title, 'services_section')}>
|
||||
<Card className="p-6 h-full group cursor-pointer border-[#E5E5E5] hover:border-[#C41E3A] transition-colors">
|
||||
<CardContent className="p-0">
|
||||
<div className="w-12 h-12 rounded-xl bg-[#F5F5F5] flex items-center justify-center mb-4 group-hover:bg-[#C41E3A] transition-all duration-300">
|
||||
@@ -128,7 +129,7 @@ export function ServicesSection({ config }: ServicesSectionProps) {
|
||||
className="text-center mt-12"
|
||||
>
|
||||
<Button variant="outline" size="lg" className="group" asChild>
|
||||
<Link href="/services">
|
||||
<Link href="/services" onClick={() => trackButtonClick('查看全部服务', 'services_section')}>
|
||||
查看全部服务
|
||||
<ArrowRight className="ml-2 w-4 h-4 transition-transform group-hover:translate-x-1" />
|
||||
</Link>
|
||||
|
||||
Reference in New Issue
Block a user