This commit is contained in:
2025-12-11 11:30:18 +08:00
parent a339acd5b0
commit 0e689b5f8d
21 changed files with 1311 additions and 95 deletions
+62
View File
@@ -0,0 +1,62 @@
import React from 'react';
import Image from 'next/image';
const About: React.FC = () => {
return (
<section id="about" className="py-24 bg-feie-cream relative">
<div className="container mx-auto px-6">
<div className="flex flex-col md:flex-row items-center gap-16">
{/* Image/Visual Area */}
<div className="w-full md:w-1/2 relative">
<div className="aspect-4/5 bg-feie-dark rounded-sm overflow-hidden relative shadow-xl">
<Image
src="/assets/186-800x1000-grayscale.jpg"
alt="Office architecture"
fill
className="object-cover opacity-80 hover:scale-105 transition-transform duration-700"
/>
<div className="absolute inset-0 border border-feie-gold/30 m-4 pointer-events-none"></div>
</div>
<div className="absolute -bottom-10 -right-10 w-48 h-48 bg-feie-gold/10 -z-10 rounded-full blur-3xl"></div>
</div>
{/* Text Content */}
<div className="w-full md:w-1/2 space-y-8">
<h2 className="text-sm font-bold tracking-widest text-feie-gold uppercase mb-2">关于我们 • About Us</h2>
<h3 className="text-4xl md:text-5xl font-serif text-feie-dark leading-tight">
专注技术沉淀 <br />
<span className="italic text-gray-500">成就卓越品质</span>
</h3>
<div className="space-y-6 text-gray-600 font-light leading-relaxed">
<p>
南京市肥鹅信息技术有限公司坐落于历史悠久的六朝古都——南京。我们是一家专注于前沿信息技术研发与应用的高新技术企业。
</p>
<p>
自成立以来,我们始终秉承"技术驱动、服务至上"的理念,深耕软件开发、系统集成及数字化转型咨询领域。我们拥有一支经验丰富、富有创造力的技术团队,致力于通过代码改变世界,用智慧连接未来。
</p>
<p>
在溧水区这片充满活力的创新热土上,我们正以稳健的步伐,为各行各业的客户提供量身定制的IT解决方案,助力企业在数字经济浪潮中乘风破浪。
</p>
</div>
<div className="pt-4 grid grid-cols-2 gap-8">
<div>
<h4 className="text-3xl font-serif text-feie-gold">100+</h4>
<p className="text-sm text-gray-500 uppercase tracking-wider mt-1">成功案例</p>
</div>
<div>
<h4 className="text-3xl font-serif text-feie-gold">24/7</h4>
<p className="text-sm text-gray-500 uppercase tracking-wider mt-1">技术支持</p>
</div>
</div>
</div>
</div>
</div>
</section>
);
};
export default About;
+278
View File
@@ -0,0 +1,278 @@
'use client';
import React, { useState } from 'react';
import { MapPin, Phone, Mail } from 'lucide-react';
interface FormData {
name: string;
phone: string;
email: string;
description: string;
}
interface FormErrors {
name?: string;
phone?: string;
email?: string;
description?: string;
}
const Contact: React.FC = () => {
const [formData, setFormData] = useState<FormData>({
name: '',
phone: '',
email: '',
description: '',
});
const [errors, setErrors] = useState<FormErrors>({});
const [isSubmitting, setIsSubmitting] = useState(false);
const [submitStatus, setSubmitStatus] = useState<{type: 'success' | 'error', message: string} | null>(null);
const validateForm = (): boolean => {
const newErrors: FormErrors = {};
if (!formData.name.trim()) {
newErrors.name = '请输入姓名';
}
const phoneRegex = /^1[3-9]\d{9}$/;
if (!formData.phone.trim()) {
newErrors.phone = '请输入电话';
} else if (!phoneRegex.test(formData.phone)) {
newErrors.phone = '请输入正确的手机号';
}
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!formData.email.trim()) {
newErrors.email = '请输入邮箱';
} else if (!emailRegex.test(formData.email)) {
newErrors.email = '请输入正确的邮箱地址';
}
if (!formData.description.trim()) {
newErrors.description = '请描述您的需求';
}
setErrors(newErrors);
return Object.keys(newErrors).length === 0;
};
const handleChange = (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {
const { name, value } = e.target;
setFormData(prev => ({ ...prev, [name]: value }));
// 清除该字段的错误
if (errors[name as keyof FormErrors]) {
setErrors(prev => ({ ...prev, [name]: undefined }));
}
};
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
if (!validateForm()) {
return;
}
setIsSubmitting(true);
setSubmitStatus(null);
try {
const response = await fetch('/api/messages', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(formData),
});
const data = await response.json();
if (response.ok) {
setSubmitStatus({
type: 'success',
message: data.message || '留言提交成功,我们会尽快与您联系!'
});
// 清空表单
setFormData({
name: '',
phone: '',
email: '',
description: '',
});
} else {
setSubmitStatus({
type: 'error',
message: data.error || '提交失败,请稍后再试'
});
}
} catch (error) {
console.error('提交错误:', error);
setSubmitStatus({
type: 'error',
message: '网络错误,请检查网络连接后重试'
});
} finally {
setIsSubmitting(false);
}
};
return (
<section id="contact" className="py-24 bg-feie-dark text-feie-white relative overflow-hidden">
{/* Abstract background element */}
<div className="absolute top-0 left-0 w-full h-full opacity-10 pointer-events-none">
<div className="absolute top-1/2 left-1/4 w-96 h-96 bg-feie-gold rounded-full blur-[120px]"></div>
</div>
<div className="container mx-auto px-6 relative z-10">
<div className="grid grid-cols-1 lg:grid-cols-2 gap-16">
<div className="space-y-8">
<div>
<h2 className="text-sm font-bold tracking-widest text-feie-gold uppercase mb-3">联系方式 • Contact</h2>
<h3 className="text-4xl md:text-5xl font-serif leading-tight">
期待与您的合作 <br/>
<span className="text-feie-white/50">共创价值</span>
</h3>
</div>
<p className="text-gray-400 font-light text-lg">
无论您有项目需求还是技术咨询,我们都随时准备为您提供专业的解答和服务。
</p>
<div className="space-y-6 pt-6">
<div className="flex items-start gap-4 group">
<div className="p-3 bg-white/5 rounded-sm group-hover:bg-feie-gold/20 transition-colors border border-white/10">
<MapPin className="w-6 h-6 text-feie-gold" />
</div>
<div>
<p className="text-sm text-gray-400 uppercase tracking-wider mb-1">注册地址</p>
<p className="text-xl font-serif">江苏省南京市溧水区永阳街道中大街81号8幢1630室</p>
</div>
</div>
<div className="flex items-start gap-4 group">
<div className="p-3 bg-white/5 rounded-sm group-hover:bg-feie-gold/20 transition-colors border border-white/10">
<Phone className="w-6 h-6 text-feie-gold" />
</div>
<div>
<p className="text-sm text-gray-400 uppercase tracking-wider mb-1">联系电话</p>
<p className="text-xl font-serif">19844561014</p>
</div>
</div>
<div className="flex items-start gap-4 group">
<div className="p-3 bg-white/5 rounded-sm group-hover:bg-feie-gold/20 transition-colors border border-white/10">
<Mail className="w-6 h-6 text-feie-gold" />
</div>
<div>
<p className="text-sm text-gray-400 uppercase tracking-wider mb-1">电子邮箱</p>
<a href="mailto:feie9454@gmail.com" className="text-xl font-serif hover:text-feie-gold transition-colors">
feie9454@gmail.com
</a>
</div>
</div>
</div>
</div>
<div className="bg-feie-cream p-8 md:p-10 rounded-sm text-feie-dark shadow-2xl">
<h4 className="text-2xl font-serif mb-6">在线留言</h4>
{submitStatus && (
<div className={`mb-6 p-4 rounded ${
submitStatus.type === 'success'
? 'bg-green-100 text-green-800 border border-green-300'
: 'bg-red-100 text-red-800 border border-red-300'
}`}>
{submitStatus.message}
</div>
)}
<form className="space-y-6" onSubmit={handleSubmit}>
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
<div>
<label className="block text-sm font-bold uppercase tracking-wider text-gray-500 mb-2">
姓名 <span className="text-red-500">*</span>
</label>
<input
type="text"
name="name"
value={formData.name}
onChange={handleChange}
className={`w-full bg-white border-b-2 p-3 focus:border-feie-gold outline-none transition-colors ${
errors.name ? 'border-red-500' : 'border-gray-200'
}`}
placeholder="您的姓名"
/>
{errors.name && <p className="text-red-500 text-sm mt-1">{errors.name}</p>}
</div>
<div>
<label className="block text-sm font-bold uppercase tracking-wider text-gray-500 mb-2">
电话 <span className="text-red-500">*</span>
</label>
<input
type="tel"
name="phone"
value={formData.phone}
onChange={handleChange}
className={`w-full bg-white border-b-2 p-3 focus:border-feie-gold outline-none transition-colors ${
errors.phone ? 'border-red-500' : 'border-gray-200'
}`}
placeholder="联系电话"
/>
{errors.phone && <p className="text-red-500 text-sm mt-1">{errors.phone}</p>}
</div>
</div>
<div>
<label className="block text-sm font-bold uppercase tracking-wider text-gray-500 mb-2">
邮箱 <span className="text-red-500">*</span>
</label>
<input
type="email"
name="email"
value={formData.email}
onChange={handleChange}
className={`w-full bg-white border-b-2 p-3 focus:border-feie-gold outline-none transition-colors ${
errors.email ? 'border-red-500' : 'border-gray-200'
}`}
placeholder="example@email.com"
/>
{errors.email && <p className="text-red-500 text-sm mt-1">{errors.email}</p>}
</div>
<div>
<label className="block text-sm font-bold uppercase tracking-wider text-gray-500 mb-2">
需求描述 <span className="text-red-500">*</span>
</label>
<textarea
rows={4}
name="description"
value={formData.description}
onChange={handleChange}
className={`w-full bg-white border-b-2 p-3 focus:border-feie-gold outline-none transition-colors resize-none ${
errors.description ? 'border-red-500' : 'border-gray-200'
}`}
placeholder="请简要描述您的需求..."
></textarea>
{errors.description && <p className="text-red-500 text-sm mt-1">{errors.description}</p>}
</div>
<button
type="submit"
disabled={isSubmitting}
className={`w-full py-4 font-serif font-bold uppercase tracking-widest transition-colors duration-300 ${
isSubmitting
? 'bg-gray-400 text-gray-200 cursor-not-allowed'
: 'bg-feie-dark text-feie-white hover:bg-feie-gold'
}`}
>
{isSubmitting ? '发送中...' : '发送信息'}
</button>
</form>
</div>
</div>
</div>
</section>
);
};
export default Contact;
+21
View File
@@ -0,0 +1,21 @@
import React from 'react';
const Footer: React.FC = () => {
return (
<footer className="bg-feie-dark text-feie-white border-t border-white/10 py-12">
<div className="container mx-auto px-6 flex flex-col md:flex-row justify-between items-center gap-6">
<div className="text-center md:text-left">
<h5 className="font-serif text-xl font-bold mb-2">南京市肥鹅信息技术有限公司</h5>
<p className="text-gray-500 text-sm">© {new Date().getFullYear()} Nanjing Feie Information Technology Co., Ltd. All rights reserved.</p>
</div>
<div className="flex gap-6 text-sm text-gray-400">
<a href="#" className="hover:text-feie-gold transition-colors">隐私政策</a>
<a href="#" className="hover:text-feie-gold transition-colors">服务条款</a>
</div>
</div>
</footer>
);
};
export default Footer;
+171
View File
@@ -0,0 +1,171 @@
'use client';
import React, { useRef, useMemo } from 'react';
import { Canvas, useFrame } from '@react-three/fiber';
import { Float, Stars } from '@react-three/drei';
import * as THREE from 'three';
// ------------------- Three.js Components -------------------
const GeometryArt = () => {
const meshRef = useRef<THREE.Mesh>(null);
useFrame((state) => {
if (meshRef.current) {
meshRef.current.rotation.x = state.clock.getElapsedTime() * 0.1;
meshRef.current.rotation.y = state.clock.getElapsedTime() * 0.15;
}
});
return (
<Float speed={1.5} rotationIntensity={0.5} floatIntensity={0.5}>
<mesh ref={meshRef} position={[2, 0, 0]} scale={1.8}>
<icosahedronGeometry args={[1, 1]} />
<meshStandardMaterial
color="#C5A059"
wireframe
transparent
opacity={0.3}
roughness={0}
metalness={1}
/>
</mesh>
<mesh position={[2, 0, 0]} scale={0.5}>
<sphereGeometry args={[1, 32, 32]} />
<meshStandardMaterial
color="#C5A059"
emissive="#C5A059"
emissiveIntensity={0.5}
roughness={0.2}
metalness={1}
/>
</mesh>
</Float>
);
};
const ConnectingLines = () => {
// Create random connections mimicking a network
const count = 40;
const lines = useMemo(() => {
const points: [number, number, number][] = [];
// Use a fixed seed for consistent but pseudo-random positioning
const seed = 12345;
const seededRandom = (i: number) => {
const x = Math.sin(seed + i * 12.9898) * 43758.5453123;
return x - Math.floor(x);
};
for (let i = 0; i < count; i++) {
points.push([
(seededRandom(i * 3) - 0.5) * 10,
(seededRandom(i * 3 + 1) - 0.5) * 6,
(seededRandom(i * 3 + 2) - 0.5) * 5
]);
}
return points;
}, []);
const ref = useRef<THREE.Group>(null);
useFrame((state) => {
if (ref.current) {
ref.current.rotation.y = -state.clock.getElapsedTime() * 0.05;
}
});
return (
<group ref={ref}>
{lines.map((pos, i) => (
<mesh key={i} position={new THREE.Vector3(...pos)}>
<sphereGeometry args={[0.02, 8, 8]} />
<meshBasicMaterial color="#ffffff" opacity={0.4} transparent />
</mesh>
))}
</group>
)
}
const Scene = () => {
return (
<>
<ambientLight intensity={0.2} />
<pointLight position={[10, 10, 10]} intensity={1.5} color="#C5A059" />
<pointLight position={[-10, -10, -10]} intensity={0.5} color="#4c4c4c" />
<spotLight position={[0, 5, 0]} angle={0.3} penumbra={1} intensity={2} color="white" />
<GeometryArt />
<ConnectingLines />
<Stars radius={100} depth={50} count={5000} factor={4} saturation={0} fade speed={1} />
</>
);
};
// ------------------- Main Component -------------------
const Hero: React.FC = () => {
return (
<section id="hero" className="relative w-full h-screen bg-feie-dark overflow-hidden">
{/* 3D Canvas Layer */}
<div className="absolute inset-0 z-0">
<Canvas camera={{ position: [0, 0, 6], fov: 45 }}>
<Scene />
</Canvas>
</div>
{/* Content Overlay */}
<div className="absolute inset-0 z-10 flex items-center">
<div className="container mx-auto px-6 grid grid-cols-1 md:grid-cols-2">
<div className="text-left space-y-6">
<div className="inline-block px-3 py-1 border border-feie-gold/50 rounded-full">
<span className="text-feie-gold text-xs font-serif tracking-widest uppercase">
Est. Nanjing • Technology Leader
</span>
</div>
<h1 className="text-5xl md:text-7xl font-serif text-feie-white leading-tight">
数字化未来的 <br />
<span className="text-feie-gold italic">构建者</span>
</h1>
<p className="text-feie-white/70 text-lg md:text-xl font-light max-w-md leading-relaxed">
南京市肥鹅信息技术有限公司致力于为企业提供卓越的数字化解决方案,以创新技术驱动商业价值。
</p>
<div className="pt-8 flex gap-4">
<a
href="#services"
className="px-8 py-3 bg-feie-gold text-feie-white font-serif hover:bg-yellow-600 transition-colors duration-300 rounded-sm"
>
探索服务
</a>
<a
href="#contact"
className="px-8 py-3 border border-feie-white text-feie-white font-serif hover:bg-feie-white hover:text-feie-dark transition-colors duration-300 rounded-sm"
>
联系我们
</a>
</div>
</div>
{/* Right side is empty to allow the 3D visual to shine */}
<div className="hidden md:block"></div>
</div>
</div>
{/* Scroll indicator */}
<div className="absolute bottom-8 left-1/2 transform -translate-x-1/2 z-10 animate-bounce">
<svg
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="#FFFFFF"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
className="opacity-50"
>
<path d="M12 5v14M19 12l-7 7-7-7"/>
</svg>
</div>
</section>
);
};
export default Hero;
+100
View File
@@ -0,0 +1,100 @@
'use client';
import React, { useState, useEffect } from 'react';
import { Menu, X } from 'lucide-react';
const navItems = [
{ label: '首页', href: '#hero' },
{ label: '关于我们', href: '#about' },
{ label: '核心业务', href: '#services' },
{ label: '联系方式', href: '#contact' },
];
const Navbar: React.FC = () => {
const [isScrolled, setIsScrolled] = useState(false);
const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false);
useEffect(() => {
const handleScroll = () => {
setIsScrolled(window.scrollY > 50);
};
window.addEventListener('scroll', handleScroll);
return () => window.removeEventListener('scroll', handleScroll);
}, []);
return (
<nav
className={`fixed top-0 left-0 w-full z-50 transition-all duration-300 ${
isScrolled
? 'bg-feie-cream/90 backdrop-blur-md shadow-sm py-4'
: 'bg-transparent py-6'
}`}
>
<div className="container mx-auto px-6 flex justify-between items-center">
<a href="#" className="flex items-center gap-2 group">
<div className={`w-8 h-8 rounded-sm border-2 flex items-center justify-center transition-colors ${isScrolled ? 'border-feie-dark text-feie-dark' : 'border-feie-white text-feie-white'}`}>
<span className="font-serif font-bold text-lg">F</span>
</div>
<span className={`font-serif text-xl font-bold tracking-wide transition-colors ${isScrolled ? 'text-feie-dark' : 'text-feie-white'}`}>
FEIE TECH
</span>
</a>
{/* Desktop Menu */}
<div className="hidden md:flex items-center space-x-8">
{navItems.map((item) => (
<a
key={item.label}
href={item.href}
className={`font-serif text-sm tracking-widest uppercase hover:text-feie-gold transition-colors duration-300 ${
isScrolled ? 'text-feie-dark' : 'text-feie-white/90'
}`}
>
{item.label}
</a>
))}
<a
href="#contact"
className={`px-5 py-2 border font-serif text-sm transition-all duration-300 ${
isScrolled
? 'border-feie-dark text-feie-dark hover:bg-feie-dark hover:text-feie-white'
: 'border-feie-white text-feie-white hover:bg-feie-white hover:text-feie-dark'
}`}
>
合作咨询
</a>
</div>
{/* Mobile Toggle */}
<button
className="md:hidden focus:outline-none"
onClick={() => setIsMobileMenuOpen(!isMobileMenuOpen)}
>
{isMobileMenuOpen ? (
<X className={isScrolled ? 'text-feie-dark' : 'text-feie-white'} />
) : (
<Menu className={isScrolled ? 'text-feie-dark' : 'text-feie-white'} />
)}
</button>
</div>
{/* Mobile Menu */}
{isMobileMenuOpen && (
<div className="md:hidden absolute top-full left-0 w-full bg-feie-cream border-t border-gray-200 py-4 shadow-lg flex flex-col items-center space-y-4">
{navItems.map((item) => (
<a
key={item.label}
href={item.href}
className="font-serif text-feie-dark hover:text-feie-gold"
onClick={() => setIsMobileMenuOpen(false)}
>
{item.label}
</a>
))}
</div>
)}
</nav>
);
};
export default Navbar;
+80
View File
@@ -0,0 +1,80 @@
import React from 'react';
import { Monitor, Server, Code, Database, Globe, Shield } from 'lucide-react';
import { ServiceItem } from '../types';
const services: ServiceItem[] = [
{
title: '定制软件开发',
description: '根据企业独特需求,打造专属的Web应用、移动端APP及桌面软件,优化业务流程。',
icon: Code,
},
{
title: '企业数字化转型',
description: '提供全方位的数字化咨询与落地实施方案,助力传统企业实现智能化升级。',
icon: Monitor,
},
{
title: '系统集成服务',
description: '打破信息孤岛,实现异构系统间的数据互通与功能协同,提升整体运营效率。',
icon: Server,
},
{
title: '大数据分析',
description: '挖掘数据价值,提供可视化报表与智能决策支持,让数据成为企业的核心资产。',
icon: Database,
},
{
title: '云服务与部署',
description: '提供安全可靠的云端架构设计、迁移及运维服务,保障业务的高可用性。',
icon: Globe,
},
{
title: '信息安全保障',
description: '构建多层次的安全防护体系,保护企业核心数据资产不受威胁。',
icon: Shield,
},
];
const Services: React.FC = () => {
return (
<section id="services" className="py-24 bg-white">
<div className="container mx-auto px-6">
<div className="text-center max-w-3xl mx-auto mb-16">
<h2 className="text-sm font-bold tracking-widest text-feie-gold uppercase mb-3">核心业务 • Services</h2>
<h3 className="text-3xl md:text-4xl font-serif text-feie-dark mb-6">
全方位技术解决方案
</h3>
<div className="w-16 h-1 bg-feie-dark mx-auto"></div>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
{services.map((service, index) => (
<div
key={index}
className="group p-8 border border-gray-100 bg-feie-cream/30 hover:bg-feie-dark hover:border-feie-dark transition-all duration-500 rounded-sm relative overflow-hidden"
>
<div className="absolute top-0 right-0 w-24 h-24 bg-feie-gold/10 rounded-bl-full -mr-4 -mt-4 transition-all duration-500 group-hover:bg-feie-gold/20"></div>
<service.icon
className="w-10 h-10 text-feie-gold mb-6 group-hover:text-feie-gold transition-colors duration-300"
strokeWidth={1.5}
/>
<h4 className="text-xl font-serif font-bold text-feie-dark mb-4 group-hover:text-feie-white transition-colors duration-300">
{service.title}
</h4>
<p className="text-gray-600 font-light leading-relaxed group-hover:text-gray-300 transition-colors duration-300">
{service.description}
</p>
<div className="mt-6 w-8 h-px bg-feie-gold group-hover:w-full transition-all duration-500"></div>
</div>
))}
</div>
</div>
</section>
);
};
export default Services;