build: 更新Next.js配置以支持静态导出并添加新依赖

更新next.config.ts文件以支持静态导出功能,并添加了多个新的依赖项到package.json中,包括UI组件库和动画库。同时生成了构建相关的文件和配置。
This commit is contained in:
张翔
2026-02-02 17:59:29 +08:00
parent f9df7b4d8f
commit 150024b6ac
443 changed files with 9531 additions and 120 deletions
+183
View File
@@ -0,0 +1,183 @@
import { COMPANY_INFO, STATS } from '@/lib/constants';
import { Badge } from '@/components/ui/badge';
import { Card, CardContent } from '@/components/ui/card';
import { Lightbulb, Users, Target, Award, MapPin, Mail, Phone } from 'lucide-react';
export const metadata = {
title: `关于我们 - ${COMPANY_INFO.name}`,
description: `了解${COMPANY_INFO.name}的发展历程、企业文化和核心价值观。成立于2026年,专注于企业数字化转型服务。`,
};
export default function AboutPage() {
const values = [
{
icon: Lightbulb,
title: '创新驱动',
description: '持续探索前沿技术,以创新思维解决业务挑战,为客户创造差异化价值',
},
{
icon: Users,
title: '客户至上',
description: '深入理解客户需求,提供个性化解决方案,建立长期合作伙伴关系',
},
{
icon: Target,
title: '追求卓越',
description: '精益求精的工作态度,确保每个项目都达到最高质量标准',
},
{
icon: Award,
title: '诚信负责',
description: '恪守商业道德,对承诺负责,赢得客户和社会的信任与尊重',
},
];
const milestones = [
{
date: '2026年1月15日',
title: '公司成立',
description: '四川睿新致远科技有限公司在成都龙泉驿区正式成立,开始提供软件开发服务',
},
{
date: '2026年1月20日',
title: '推出转型方案',
description: '发布企业数字化转型解决方案,整合云计算、大数据、人工智能等前沿技术',
},
{
date: '2026年1月25日',
title: '战略合作',
description: '与本地知名制造企业签署战略合作协议,共同打造智能制造示范工厂',
},
{
date: '2026年2月1日',
title: '行业认可',
description: '正式加入四川省软件行业协会,成为协会成员单位',
},
{
date: '2026年2月2日',
title: '官网上线',
description: '公司官方网站正式上线,为客户提供更加便捷的信息获取渠道',
},
];
return (
<div className="pt-32 pb-20">
<div className="container-custom">
{/* 头部介绍 */}
<div className="max-w-4xl mx-auto">
<div className="text-center mb-16">
<Badge variant="outline" className="mb-4">
</Badge>
<h1 className="text-4xl sm:text-5xl font-bold text-black mb-6">
{COMPANY_INFO.shortName}
</h1>
<p className="text-lg text-gray-600">
{COMPANY_INFO.slogan}
</p>
</div>
{/* 公司简介 */}
<div className="prose prose-lg max-w-none mb-16">
<h2 className="text-2xl font-bold text-black mb-4"></h2>
<p className="text-gray-600 mb-6 leading-relaxed">
{COMPANY_INFO.name}{COMPANY_INFO.founded}115{COMPANY_INFO.location}驿12
</p>
<p className="text-gray-600 mb-6 leading-relaxed">
"专注科技创新,驱动智慧未来"
</p>
</div>
{/* 数据统计 */}
<div className="grid grid-cols-2 md:grid-cols-4 gap-6 mb-16">
{STATS.map((stat, idx) => (
<Card key={idx} className="text-center">
<CardContent className="pt-6">
<div className="text-3xl sm:text-4xl font-bold text-black mb-2">{stat.value}</div>
<div className="text-sm text-gray-600">{stat.label}</div>
</CardContent>
</Card>
))}
</div>
{/* 核心价值观 */}
<div className="mb-16">
<h2 className="text-2xl font-bold text-black mb-6 text-center"></h2>
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
{values.map((value, idx) => (
<Card key={idx} className="group hover:shadow-md transition-shadow">
<CardContent className="p-6">
<div className="flex items-start gap-4">
<div className="p-3 bg-gray-100 rounded-lg group-hover:bg-black group-hover:text-white transition-colors">
<value.icon className="w-6 h-6" />
</div>
<div>
<h3 className="font-semibold text-lg mb-2">{value.title}</h3>
<p className="text-gray-600 text-sm leading-relaxed">{value.description}</p>
</div>
</div>
</CardContent>
</Card>
))}
</div>
</div>
{/* 发展历程 */}
<div className="mb-16">
<h2 className="text-2xl font-bold text-black mb-6 text-center"></h2>
<div className="space-y-6">
{milestones.map((milestone, idx) => (
<div key={idx} className="flex gap-4 md:gap-6">
<div className="w-32 md:w-40 flex-shrink-0">
<div className="font-semibold text-black text-sm md:text-base">{milestone.date}</div>
</div>
<div className="flex-1 pb-6 border-l-2 border-gray-200 pl-6 relative">
<div className="absolute -left-[9px] top-1 w-4 h-4 bg-black rounded-full"></div>
<h3 className="font-semibold text-black mb-1">{milestone.title}</h3>
<p className="text-gray-600 text-sm leading-relaxed">{milestone.description}</p>
</div>
</div>
))}
</div>
</div>
{/* 联系我们 */}
<div className="bg-gray-50 rounded-2xl p-8">
<h2 className="text-2xl font-bold text-black mb-6 text-center"></h2>
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
<div className="flex items-center gap-3">
<div className="p-2 bg-white rounded-lg">
<MapPin className="w-5 h-5 text-gray-600" />
</div>
<div>
<p className="text-sm text-gray-500"></p>
<p className="text-sm font-medium">{COMPANY_INFO.address}</p>
</div>
</div>
<div className="flex items-center gap-3">
<div className="p-2 bg-white rounded-lg">
<Mail className="w-5 h-5 text-gray-600" />
</div>
<div>
<p className="text-sm text-gray-500"></p>
<p className="text-sm font-medium">{COMPANY_INFO.email}</p>
</div>
</div>
<div className="flex items-center gap-3">
<div className="p-2 bg-white rounded-lg">
<Phone className="w-5 h-5 text-gray-600" />
</div>
<div>
<p className="text-sm text-gray-500"></p>
<p className="text-sm font-medium">{COMPANY_INFO.phone}</p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
);
}
+198
View File
@@ -0,0 +1,198 @@
'use client';
import { useState } from 'react';
import { COMPANY_INFO } from '@/lib/constants';
import { Badge } from '@/components/ui/badge';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Textarea } from '@/components/ui/textarea';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Mail, Phone, MapPin, Send, Loader2 } from 'lucide-react';
export default function ContactPage() {
const [isSubmitting, setIsSubmitting] = useState(false);
const [isSubmitted, setIsSubmitted] = useState(false);
async function handleSubmit(formData: FormData) {
setIsSubmitting(true);
// Simulate form submission
await new Promise(resolve => setTimeout(resolve, 1500));
setIsSubmitting(false);
setIsSubmitted(true);
}
return (
<div className="pt-32 pb-20">
<div className="container-custom">
<div className="text-center max-w-3xl mx-auto mb-16">
<Badge variant="outline" className="mb-4">
</Badge>
<h1 className="text-4xl sm:text-5xl font-bold text-black mb-6">
</h1>
<p className="text-lg text-gray-600">
</p>
</div>
<div className="grid grid-cols-1 lg:grid-cols-2 gap-12 max-w-6xl mx-auto">
{/* Contact Info */}
<div className="space-y-8">
<Card>
<CardHeader>
<CardTitle></CardTitle>
</CardHeader>
<CardContent className="space-y-6">
<div className="flex items-start gap-4">
<div className="w-10 h-10 bg-black rounded-lg flex items-center justify-center flex-shrink-0">
<MapPin className="w-5 h-5 text-white" />
</div>
<div>
<h3 className="font-semibold text-black"></h3>
<p className="text-gray-600">{COMPANY_INFO.address}</p>
</div>
</div>
<div className="flex items-start gap-4">
<div className="w-10 h-10 bg-black rounded-lg flex items-center justify-center flex-shrink-0">
<Phone className="w-5 h-5 text-white" />
</div>
<div>
<h3 className="font-semibold text-black"></h3>
<p className="text-gray-600">{COMPANY_INFO.phone}</p>
</div>
</div>
<div className="flex items-start gap-4">
<div className="w-10 h-10 bg-black rounded-lg flex items-center justify-center flex-shrink-0">
<Mail className="w-5 h-5 text-white" />
</div>
<div>
<h3 className="font-semibold text-black"></h3>
<p className="text-gray-600">{COMPANY_INFO.email}</p>
</div>
</div>
</CardContent>
</Card>
<Card>
<CardHeader>
<CardTitle></CardTitle>
</CardHeader>
<CardContent>
<div className="space-y-2">
<div className="flex justify-between">
<span className="text-gray-600"></span>
<span className="text-black font-medium">9:00 - 18:00</span>
</div>
<div className="flex justify-between">
<span className="text-gray-600"></span>
<span className="text-black font-medium">9:00 - 12:00</span>
</div>
<div className="flex justify-between">
<span className="text-gray-600"></span>
<span className="text-gray-400"></span>
</div>
</div>
</CardContent>
</Card>
</div>
{/* Contact Form */}
<Card>
<CardHeader>
<CardTitle></CardTitle>
</CardHeader>
<CardContent>
{isSubmitted ? (
<div className="text-center py-12">
<div className="w-16 h-16 bg-green-100 rounded-full flex items-center justify-center mx-auto mb-4">
<Send className="w-8 h-8 text-green-600" />
</div>
<h3 className="text-xl font-semibold text-black mb-2"></h3>
<p className="text-gray-600"></p>
</div>
) : (
<form action={handleSubmit} className="space-y-6">
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
<div>
<label htmlFor="name" className="block text-sm font-medium text-gray-700 mb-2">
*
</label>
<Input
id="name"
name="name"
placeholder="请输入您的姓名"
required
/>
</div>
<div>
<label htmlFor="phone" className="block text-sm font-medium text-gray-700 mb-2">
</label>
<Input
id="phone"
name="phone"
type="tel"
placeholder="请输入您的电话"
/>
</div>
</div>
<div>
<label htmlFor="email" className="block text-sm font-medium text-gray-700 mb-2">
*
</label>
<Input
id="email"
name="email"
type="email"
placeholder="请输入您的邮箱"
required
/>
</div>
<div>
<label htmlFor="subject" className="block text-sm font-medium text-gray-700 mb-2">
*
</label>
<Input
id="subject"
name="subject"
placeholder="请输入消息主题"
required
/>
</div>
<div>
<label htmlFor="message" className="block text-sm font-medium text-gray-700 mb-2">
*
</label>
<Textarea
id="message"
name="message"
placeholder="请输入您想要咨询的内容"
rows={5}
required
/>
</div>
<Button type="submit" className="w-full" disabled={isSubmitting}>
{isSubmitting ? (
<>
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
...
</>
) : (
<>
<Send className="mr-2 h-4 w-4" />
</>
)}
</Button>
</form>
)}
</CardContent>
</Card>
</div>
</div>
</div>
);
}
+16
View File
@@ -0,0 +1,16 @@
import { Header } from '@/components/layout/header';
import { Footer } from '@/components/layout/footer';
export default function MarketingLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<div className="min-h-screen flex flex-col">
<Header />
<main className="flex-1">{children}</main>
<Footer />
</div>
);
}
+109
View File
@@ -0,0 +1,109 @@
import { notFound } from 'next/navigation';
import { COMPANY_INFO, NEWS } from '@/lib/constants';
import { Badge } from '@/components/ui/badge';
import { Card, CardContent } from '@/components/ui/card';
import { Calendar, ArrowLeft } from 'lucide-react';
import Link from 'next/link';
import { Button } from '@/components/ui/button';
interface NewsDetailPageProps {
params: Promise<{
slug: string;
}>;
}
// 定义新闻项类型
type NewsItem = {
id: string;
title: string;
excerpt: string;
date: string;
category: string;
image: string;
content?: string;
};
export function generateStaticParams() {
return NEWS.map((news) => ({
slug: news.id,
}));
}
export async function generateMetadata({ params }: NewsDetailPageProps) {
const { slug } = await params;
const news = (NEWS as unknown as NewsItem[]).find((n) => n.id === slug);
if (!news) {
return {
title: `新闻未找到 - ${COMPANY_INFO.name}`,
};
}
return {
title: `${news.title} - ${COMPANY_INFO.name}`,
description: news.excerpt,
};
}
export default async function NewsDetailPage({ params }: NewsDetailPageProps) {
const { slug } = await params;
const news = (NEWS as unknown as NewsItem[]).find((n) => n.id === slug);
if (!news) {
notFound();
}
return (
<div className="pt-32 pb-20">
<div className="container-custom">
<div className="max-w-4xl mx-auto">
<Button variant="ghost" asChild className="mb-8">
<Link href="/news">
<ArrowLeft className="mr-2 w-4 h-4" />
</Link>
</Button>
<article>
<div className="flex items-center gap-3 mb-6">
<Badge>{news.category}</Badge>
<span className="text-sm text-gray-500 flex items-center gap-1">
<Calendar className="w-4 h-4" />
{news.date}
</span>
</div>
<h1 className="text-3xl sm:text-4xl font-bold text-black mb-8">
{news.title}
</h1>
<Card>
<CardContent className="p-8">
<div className="prose prose-lg max-w-none">
{news.content ? (
news.content.split('\n\n').map((paragraph, idx) => (
<p key={idx} className="text-gray-600 leading-relaxed mb-6">
{paragraph}
</p>
))
) : (
<>
<p className="text-gray-600 leading-relaxed">
{news.excerpt}
</p>
<p className="text-gray-600 leading-relaxed mt-6">
</p>
</>
)}
</div>
</CardContent>
</Card>
</article>
</div>
</div>
</div>
);
}
+59
View File
@@ -0,0 +1,59 @@
import Link from 'next/link';
import { COMPANY_INFO, NEWS } from '@/lib/constants';
import { Badge } from '@/components/ui/badge';
import { Card, CardContent, CardHeader, CardTitle, CardDescription } from '@/components/ui/card';
import { ArrowRight, Calendar } from 'lucide-react';
export const metadata = {
title: `新闻动态 - ${COMPANY_INFO.name}`,
description: `了解${COMPANY_INFO.name}的最新动态和行业资讯`,
};
export default function NewsPage() {
return (
<div className="pt-32 pb-20">
<div className="container-custom">
<div className="text-center max-w-3xl mx-auto mb-16">
<Badge variant="outline" className="mb-4">
</Badge>
<h1 className="text-4xl sm:text-5xl font-bold text-black mb-6">
</h1>
<p className="text-lg text-gray-600">
</p>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-8 max-w-5xl mx-auto">
{NEWS.map((news) => (
<Card key={news.id} className="h-full flex flex-col">
<CardHeader>
<div className="flex items-center gap-2 mb-3">
<Badge variant="secondary">{news.category}</Badge>
<span className="text-sm text-gray-500 flex items-center gap-1">
<Calendar className="w-3 h-3" />
{news.date}
</span>
</div>
<CardTitle className="text-xl leading-tight">{news.title}</CardTitle>
</CardHeader>
<CardContent className="flex-1 flex flex-col">
<CardDescription className="text-base leading-relaxed mb-6 flex-1">
{news.excerpt}
</CardDescription>
<Link
href={`/news/${news.id}`}
className="inline-flex items-center text-sm font-medium text-black hover:underline"
>
<ArrowRight className="ml-1 w-4 h-4" />
</Link>
</CardContent>
</Card>
))}
</div>
</div>
</div>
);
}
+25
View File
@@ -0,0 +1,25 @@
import { HeroSection } from '@/components/sections/hero-section';
import { AboutSection } from '@/components/sections/about-section';
import { ServicesSection } from '@/components/sections/services-section';
import { ProductsSection } from '@/components/sections/products-section';
import { NewsSection } from '@/components/sections/news-section';
import { ContactSection } from '@/components/sections/contact-section';
import { COMPANY_INFO } from '@/lib/constants';
export const metadata = {
title: `${COMPANY_INFO.name} - 专业科技服务提供商`,
description: COMPANY_INFO.description,
};
export default function HomePage() {
return (
<>
<HeroSection />
<AboutSection />
<ServicesSection />
<ProductsSection />
<NewsSection />
<ContactSection />
</>
);
}
+101
View File
@@ -0,0 +1,101 @@
import { COMPANY_INFO, PRODUCTS } from '@/lib/constants';
import { Badge } from '@/components/ui/badge';
import { Card, CardContent, CardHeader, CardTitle, CardDescription } from '@/components/ui/card';
import { Button } from '@/components/ui/button';
import { ArrowRight, Check, TrendingUp } from 'lucide-react';
export const metadata = {
title: `产品服务 - ${COMPANY_INFO.name}`,
description: `了解${COMPANY_INFO.name}的产品和服务解决方案,包括ERP、CRM、OA、BI、物联网和AI智能应用`,
};
export default function ProductsPage() {
return (
<div className="pt-32 pb-20">
<div className="container-custom">
<div className="text-center max-w-3xl mx-auto mb-16">
<Badge variant="outline" className="mb-4">
</Badge>
<h1 className="text-4xl sm:text-5xl font-bold text-black mb-6">
</h1>
<p className="text-lg text-gray-600">
</p>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
{PRODUCTS.map((product) => (
<Card key={product.id} className="h-full flex flex-col group hover:shadow-lg transition-shadow">
<CardHeader>
<Badge variant="secondary" className="w-fit mb-3">
{product.category}
</Badge>
<CardTitle className="text-xl">{product.title}</CardTitle>
</CardHeader>
<CardContent className="flex-1 flex flex-col">
<CardDescription className="text-base leading-relaxed mb-4 flex-1">
{product.description}
</CardDescription>
{/* 核心功能 */}
<div className="mb-4">
<p className="text-sm font-medium text-black mb-2"></p>
<div className="flex flex-wrap gap-1.5">
{product.features.slice(0, 4).map((feature, idx) => (
<span
key={idx}
className="inline-flex items-center text-xs px-2 py-1 bg-gray-100 text-gray-700 rounded"
>
<Check className="w-3 h-3 mr-1 text-green-600" />
{feature}
</span>
))}
</div>
</div>
{/* 核心价值 */}
<div className="mb-4">
<p className="text-sm font-medium text-black mb-2 flex items-center">
<TrendingUp className="w-4 h-4 mr-1 text-blue-600" />
</p>
<ul className="space-y-1">
{product.benefits.map((benefit, idx) => (
<li key={idx} className="text-xs text-gray-600 flex items-start">
<span className="text-blue-600 mr-1.5"></span>
{benefit}
</li>
))}
</ul>
</div>
<Button variant="outline" className="w-full mt-auto group-hover:bg-black group-hover:text-white transition-colors">
<ArrowRight className="ml-2 w-4 h-4" />
</Button>
</CardContent>
</Card>
))}
</div>
{/* 底部CTA */}
<div className="mt-20 text-center">
<div className="bg-gradient-to-r from-gray-50 to-gray-100 rounded-2xl p-12">
<h2 className="text-2xl sm:text-3xl font-bold text-black mb-4">
</h2>
<p className="text-gray-600 mb-8 max-w-2xl mx-auto">
</p>
<Button size="lg" className="bg-black text-white hover:bg-gray-800">
<ArrowRight className="ml-2 w-4 h-4" />
</Button>
</div>
</div>
</div>
</div>
);
}
+57
View File
@@ -0,0 +1,57 @@
import { COMPANY_INFO, SERVICES } from '@/lib/constants';
import { Badge } from '@/components/ui/badge';
import { Card, CardContent, CardHeader, CardTitle, CardDescription } from '@/components/ui/card';
import { Code, Cloud, BarChart3, Shield } from 'lucide-react';
const iconMap: Record<string, React.ComponentType<{ className?: string }>> = {
Code,
Cloud,
BarChart3,
Shield,
};
export const metadata = {
title: `核心业务 - ${COMPANY_INFO.name}`,
description: `了解${COMPANY_INFO.name}的核心业务领域和专业服务`,
};
export default function ServicesPage() {
return (
<div className="pt-32 pb-20">
<div className="container-custom">
<div className="text-center max-w-3xl mx-auto mb-16">
<Badge variant="outline" className="mb-4">
</Badge>
<h1 className="text-4xl sm:text-5xl font-bold text-black mb-6">
</h1>
<p className="text-lg text-gray-600">
</p>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-8 max-w-5xl mx-auto">
{SERVICES.map((service) => {
const Icon = iconMap[service.icon];
return (
<Card key={service.id} className="h-full">
<CardHeader>
<div className="w-14 h-14 bg-black rounded-xl flex items-center justify-center mb-4">
{Icon && <Icon className="w-7 h-7 text-white" />}
</div>
<CardTitle className="text-2xl">{service.title}</CardTitle>
</CardHeader>
<CardContent>
<CardDescription className="text-base leading-relaxed">
{service.description}
</CardDescription>
</CardContent>
</Card>
);
})}
</div>
</div>
</div>
);
}