From d06caee35a4fe99510aeddff944831f1826f727a Mon Sep 17 00:00:00 2001 From: xujiang Date: Tue, 8 Jul 2025 14:39:08 +0800 Subject: [PATCH] init ui --- ui/.gitignore | 27 + ui/app/globals.css | 63 +++ ui/app/layout.tsx | 24 + ui/app/page.tsx | 270 ++++++++++ ui/components.json | 21 + ui/components/about-view.tsx | 248 +++++++++ ui/components/contact-view.tsx | 432 +++++++++++++++ ui/components/filter-bar.tsx | 36 ++ ui/components/loading-spinner.tsx | 17 + ui/components/navigation.tsx | 83 +++ ui/components/photo-gallery.tsx | 91 ++++ ui/components/photo-modal.tsx | 160 ++++++ ui/components/theme-provider.tsx | 11 + ui/components/timeline-stats.tsx | 81 +++ ui/components/timeline-view.tsx | 185 +++++++ ui/components/ui/accordion.tsx | 58 ++ ui/components/ui/alert-dialog.tsx | 141 +++++ ui/components/ui/alert.tsx | 59 +++ ui/components/ui/aspect-ratio.tsx | 7 + ui/components/ui/avatar.tsx | 50 ++ ui/components/ui/badge.tsx | 36 ++ ui/components/ui/breadcrumb.tsx | 115 ++++ ui/components/ui/button.tsx | 56 ++ ui/components/ui/calendar.tsx | 66 +++ ui/components/ui/card.tsx | 79 +++ ui/components/ui/carousel.tsx | 262 +++++++++ ui/components/ui/chart.tsx | 365 +++++++++++++ ui/components/ui/checkbox.tsx | 30 ++ ui/components/ui/collapsible.tsx | 11 + ui/components/ui/command.tsx | 153 ++++++ ui/components/ui/context-menu.tsx | 200 +++++++ ui/components/ui/dialog.tsx | 122 +++++ ui/components/ui/drawer.tsx | 118 +++++ ui/components/ui/dropdown-menu.tsx | 200 +++++++ ui/components/ui/form.tsx | 178 +++++++ ui/components/ui/hover-card.tsx | 29 + ui/components/ui/input-otp.tsx | 71 +++ ui/components/ui/input.tsx | 22 + ui/components/ui/label.tsx | 26 + ui/components/ui/menubar.tsx | 236 +++++++++ ui/components/ui/navigation-menu.tsx | 128 +++++ ui/components/ui/pagination.tsx | 117 ++++ ui/components/ui/popover.tsx | 31 ++ ui/components/ui/progress.tsx | 28 + ui/components/ui/radio-group.tsx | 44 ++ ui/components/ui/resizable.tsx | 45 ++ ui/components/ui/scroll-area.tsx | 48 ++ ui/components/ui/select.tsx | 160 ++++++ ui/components/ui/separator.tsx | 31 ++ ui/components/ui/sheet.tsx | 140 +++++ ui/components/ui/sidebar.tsx | 763 +++++++++++++++++++++++++++ ui/components/ui/skeleton.tsx | 15 + ui/components/ui/slider.tsx | 28 + ui/components/ui/sonner.tsx | 31 ++ ui/components/ui/switch.tsx | 29 + ui/components/ui/table.tsx | 117 ++++ ui/components/ui/tabs.tsx | 55 ++ ui/components/ui/textarea.tsx | 22 + ui/components/ui/toast.tsx | 129 +++++ ui/components/ui/toaster.tsx | 35 ++ ui/components/ui/toggle-group.tsx | 61 +++ ui/components/ui/toggle.tsx | 45 ++ ui/components/ui/tooltip.tsx | 30 ++ ui/components/ui/use-mobile.tsx | 19 + ui/components/ui/use-toast.ts | 194 +++++++ ui/hooks/use-mobile.tsx | 19 + ui/hooks/use-toast.ts | 194 +++++++ ui/lib/utils.ts | 6 + ui/next.config.mjs | 14 + ui/package.json | 70 +++ ui/pnpm-lock.yaml | 5 + ui/postcss.config.mjs | 8 + ui/public/placeholder-logo.png | Bin 0 -> 568 bytes ui/public/placeholder-logo.svg | 1 + ui/public/placeholder-user.jpg | Bin 0 -> 1635 bytes ui/public/placeholder.jpg | Bin 0 -> 1064 bytes ui/public/placeholder.svg | 1 + ui/styles/globals.css | 94 ++++ ui/tailwind.config.ts | 98 ++++ ui/tsconfig.json | 27 + 80 files changed, 7321 insertions(+) create mode 100644 ui/.gitignore create mode 100644 ui/app/globals.css create mode 100644 ui/app/layout.tsx create mode 100644 ui/app/page.tsx create mode 100644 ui/components.json create mode 100644 ui/components/about-view.tsx create mode 100644 ui/components/contact-view.tsx create mode 100644 ui/components/filter-bar.tsx create mode 100644 ui/components/loading-spinner.tsx create mode 100644 ui/components/navigation.tsx create mode 100644 ui/components/photo-gallery.tsx create mode 100644 ui/components/photo-modal.tsx create mode 100644 ui/components/theme-provider.tsx create mode 100644 ui/components/timeline-stats.tsx create mode 100644 ui/components/timeline-view.tsx create mode 100644 ui/components/ui/accordion.tsx create mode 100644 ui/components/ui/alert-dialog.tsx create mode 100644 ui/components/ui/alert.tsx create mode 100644 ui/components/ui/aspect-ratio.tsx create mode 100644 ui/components/ui/avatar.tsx create mode 100644 ui/components/ui/badge.tsx create mode 100644 ui/components/ui/breadcrumb.tsx create mode 100644 ui/components/ui/button.tsx create mode 100644 ui/components/ui/calendar.tsx create mode 100644 ui/components/ui/card.tsx create mode 100644 ui/components/ui/carousel.tsx create mode 100644 ui/components/ui/chart.tsx create mode 100644 ui/components/ui/checkbox.tsx create mode 100644 ui/components/ui/collapsible.tsx create mode 100644 ui/components/ui/command.tsx create mode 100644 ui/components/ui/context-menu.tsx create mode 100644 ui/components/ui/dialog.tsx create mode 100644 ui/components/ui/drawer.tsx create mode 100644 ui/components/ui/dropdown-menu.tsx create mode 100644 ui/components/ui/form.tsx create mode 100644 ui/components/ui/hover-card.tsx create mode 100644 ui/components/ui/input-otp.tsx create mode 100644 ui/components/ui/input.tsx create mode 100644 ui/components/ui/label.tsx create mode 100644 ui/components/ui/menubar.tsx create mode 100644 ui/components/ui/navigation-menu.tsx create mode 100644 ui/components/ui/pagination.tsx create mode 100644 ui/components/ui/popover.tsx create mode 100644 ui/components/ui/progress.tsx create mode 100644 ui/components/ui/radio-group.tsx create mode 100644 ui/components/ui/resizable.tsx create mode 100644 ui/components/ui/scroll-area.tsx create mode 100644 ui/components/ui/select.tsx create mode 100644 ui/components/ui/separator.tsx create mode 100644 ui/components/ui/sheet.tsx create mode 100644 ui/components/ui/sidebar.tsx create mode 100644 ui/components/ui/skeleton.tsx create mode 100644 ui/components/ui/slider.tsx create mode 100644 ui/components/ui/sonner.tsx create mode 100644 ui/components/ui/switch.tsx create mode 100644 ui/components/ui/table.tsx create mode 100644 ui/components/ui/tabs.tsx create mode 100644 ui/components/ui/textarea.tsx create mode 100644 ui/components/ui/toast.tsx create mode 100644 ui/components/ui/toaster.tsx create mode 100644 ui/components/ui/toggle-group.tsx create mode 100644 ui/components/ui/toggle.tsx create mode 100644 ui/components/ui/tooltip.tsx create mode 100644 ui/components/ui/use-mobile.tsx create mode 100644 ui/components/ui/use-toast.ts create mode 100644 ui/hooks/use-mobile.tsx create mode 100644 ui/hooks/use-toast.ts create mode 100644 ui/lib/utils.ts create mode 100644 ui/next.config.mjs create mode 100644 ui/package.json create mode 100644 ui/pnpm-lock.yaml create mode 100644 ui/postcss.config.mjs create mode 100644 ui/public/placeholder-logo.png create mode 100644 ui/public/placeholder-logo.svg create mode 100644 ui/public/placeholder-user.jpg create mode 100644 ui/public/placeholder.jpg create mode 100644 ui/public/placeholder.svg create mode 100644 ui/styles/globals.css create mode 100644 ui/tailwind.config.ts create mode 100644 ui/tsconfig.json diff --git a/ui/.gitignore b/ui/.gitignore new file mode 100644 index 0000000..f650315 --- /dev/null +++ b/ui/.gitignore @@ -0,0 +1,27 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules + +# next.js +/.next/ +/out/ + +# production +/build + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* +.pnpm-debug.log* + +# env files +.env* + +# vercel +.vercel + +# typescript +*.tsbuildinfo +next-env.d.ts \ No newline at end of file diff --git a/ui/app/globals.css b/ui/app/globals.css new file mode 100644 index 0000000..c8fd69d --- /dev/null +++ b/ui/app/globals.css @@ -0,0 +1,63 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +@layer base { + :root { + --background: 0 0% 100%; + --foreground: 222.2 84% 4.9%; + --card: 0 0% 100%; + --card-foreground: 222.2 84% 4.9%; + --popover: 0 0% 100%; + --popover-foreground: 222.2 84% 4.9%; + --primary: 222.2 47.4% 11.2%; + --primary-foreground: 210 40% 98%; + --secondary: 210 40% 96%; + --secondary-foreground: 222.2 84% 4.9%; + --muted: 210 40% 96%; + --muted-foreground: 215.4 16.3% 46.9%; + --accent: 210 40% 96%; + --accent-foreground: 222.2 84% 4.9%; + --destructive: 0 84.2% 60.2%; + --destructive-foreground: 210 40% 98%; + --border: 214.3 31.8% 91.4%; + --input: 214.3 31.8% 91.4%; + --ring: 222.2 84% 4.9%; + --radius: 0.5rem; + } +} + +@layer base { + * { + @apply border-border; + } + body { + @apply bg-background text-foreground; + } +} + +/* Custom scrollbar */ +::-webkit-scrollbar { + width: 6px; +} + +::-webkit-scrollbar-track { + background: #f1f1f1; +} + +::-webkit-scrollbar-thumb { + background: #c1c1c1; + border-radius: 3px; +} + +::-webkit-scrollbar-thumb:hover { + background: #a8a8a8; +} + +/* Smooth transitions */ +* { + transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, + transform, filter, backdrop-filter; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-duration: 150ms; +} diff --git a/ui/app/layout.tsx b/ui/app/layout.tsx new file mode 100644 index 0000000..291fada --- /dev/null +++ b/ui/app/layout.tsx @@ -0,0 +1,24 @@ +import type React from "react" +import type { Metadata } from "next" +import { Inter } from "next/font/google" +import "./globals.css" + +const inter = Inter({ subsets: ["latin"] }) + +export const metadata: Metadata = { + title: "摄影作品集 - PhotoStudio", + description: "专业摄影师作品展示平台,记录世界的美好瞬间", + generator: 'v0.dev' +} + +export default function RootLayout({ + children, +}: { + children: React.ReactNode +}) { + return ( + + {children} + + ) +} diff --git a/ui/app/page.tsx b/ui/app/page.tsx new file mode 100644 index 0000000..e6cf2a6 --- /dev/null +++ b/ui/app/page.tsx @@ -0,0 +1,270 @@ +"use client" + +import { useState, useEffect } from "react" +import { PhotoGallery } from "@/components/photo-gallery" +import { PhotoModal } from "@/components/photo-modal" +import { Navigation } from "@/components/navigation" +import { FilterBar } from "@/components/filter-bar" +import { LoadingSpinner } from "@/components/loading-spinner" +import { TimelineView } from "@/components/timeline-view" +import { AboutView } from "@/components/about-view" +import { ContactView } from "@/components/contact-view" + +// Mock photo data with EXIF information +const mockPhotos = [ + { + id: 1, + src: "/placeholder.svg?height=600&width=800", + title: "城市夜景", + description: "繁华都市的霓虹夜色", + category: "urban", + tags: ["夜景", "城市", "建筑"], + date: "2024-01-15", + exif: { + camera: "Canon EOS R5", + lens: "24-70mm f/2.8", + settings: "f/8, 1/60s, ISO 800", + location: "上海外滩", + }, + }, + { + id: 2, + src: "/placeholder.svg?height=800&width=600", + title: "自然风光", + description: "山间晨雾缭绕的美景", + category: "nature", + tags: ["风景", "山脉", "晨雾"], + date: "2024-01-20", + exif: { + camera: "Sony A7R IV", + lens: "70-200mm f/4", + settings: "f/11, 1/125s, ISO 200", + location: "黄山", + }, + }, + { + id: 3, + src: "/placeholder.svg?height=600&width=800", + title: "人像摄影", + description: "自然光下的人像作品", + category: "portrait", + tags: ["人像", "自然光", "情绪"], + date: "2024-02-01", + exif: { + camera: "Nikon D850", + lens: "85mm f/1.4", + settings: "f/2.8, 1/200s, ISO 400", + location: "工作室", + }, + }, + { + id: 4, + src: "/placeholder.svg?height=800&width=800", + title: "街头摄影", + description: "捕捉城市生活的瞬间", + category: "street", + tags: ["街头", "生活", "瞬间"], + date: "2024-02-10", + exif: { + camera: "Fujifilm X-T4", + lens: "35mm f/1.4", + settings: "f/5.6, 1/250s, ISO 800", + location: "北京胡同", + }, + }, + { + id: 5, + src: "/placeholder.svg?height=600&width=800", + title: "建筑摄影", + description: "现代建筑的几何美学", + category: "architecture", + tags: ["建筑", "几何", "现代"], + date: "2024-02-15", + exif: { + camera: "Canon EOS R6", + lens: "16-35mm f/2.8", + settings: "f/8, 1/100s, ISO 100", + location: "深圳", + }, + }, + { + id: 6, + src: "/placeholder.svg?height=800&width=600", + title: "微距摄影", + description: "花朵的细节之美", + category: "macro", + tags: ["微距", "花卉", "细节"], + date: "2024-02-20", + exif: { + camera: "Sony A7R V", + lens: "90mm f/2.8 Macro", + settings: "f/5.6, 1/160s, ISO 200", + location: "植物园", + }, + }, + { + id: 7, + src: "/placeholder.svg?height=600&width=800", + title: "日落风景", + description: "海边的金色黄昏", + category: "nature", + tags: ["日落", "海景", "黄昏"], + date: "2023-12-10", + exif: { + camera: "Canon EOS R5", + lens: "24-105mm f/4", + settings: "f/8, 1/125s, ISO 100", + location: "三亚海滩", + }, + }, + { + id: 8, + src: "/placeholder.svg?height=800&width=600", + title: "古建筑", + description: "传统建筑的韵味", + category: "architecture", + tags: ["古建筑", "传统", "文化"], + date: "2023-11-25", + exif: { + camera: "Sony A7R IV", + lens: "50mm f/1.8", + settings: "f/5.6, 1/200s, ISO 400", + location: "故宫", + }, + }, +] + +export default function HomePage() { + const [photos, setPhotos] = useState(mockPhotos) + const [filteredPhotos, setFilteredPhotos] = useState(mockPhotos) + const [selectedPhoto, setSelectedPhoto] = useState(null) + const [isLoading, setIsLoading] = useState(true) + const [activeCategory, setActiveCategory] = useState("all") + const [activeTab, setActiveTab] = useState("gallery") + + useEffect(() => { + // Simulate loading + const timer = setTimeout(() => { + setIsLoading(false) + }, 1500) + + return () => clearTimeout(timer) + }, []) + + const handleFilter = (category: string) => { + setActiveCategory(category) + if (category === "all") { + setFilteredPhotos(photos) + } else { + setFilteredPhotos(photos.filter((photo) => photo.category === category)) + } + } + + const handlePhotoClick = (photo: any) => { + setSelectedPhoto(photo) + } + + const handleCloseModal = () => { + setSelectedPhoto(null) + } + + const handlePrevPhoto = () => { + if (!selectedPhoto) return + const currentPhotos = activeTab === "gallery" ? filteredPhotos : photos + const currentIndex = currentPhotos.findIndex((p) => p.id === selectedPhoto.id) + const prevIndex = currentIndex > 0 ? currentIndex - 1 : currentPhotos.length - 1 + setSelectedPhoto(currentPhotos[prevIndex]) + } + + const handleNextPhoto = () => { + if (!selectedPhoto) return + const currentPhotos = activeTab === "gallery" ? filteredPhotos : photos + const currentIndex = currentPhotos.findIndex((p) => p.id === selectedPhoto.id) + const nextIndex = currentIndex < currentPhotos.length - 1 ? currentIndex + 1 : 0 + setSelectedPhoto(currentPhotos[nextIndex]) + } + + const handleTabChange = (tab: string) => { + setActiveTab(tab) + // Reset filters when switching tabs + if (tab === "timeline") { + setActiveCategory("all") + setFilteredPhotos(photos) + } + } + + const handleContactClick = () => { + setActiveTab("contact") + } + + const getPageTitle = () => { + switch (activeTab) { + case "gallery": + return "摄影作品集" + case "timeline": + return "创作时间线" + case "about": + return "关于我" + case "contact": + return "联系合作" + default: + return "摄影作品集" + } + } + + const getPageDescription = () => { + switch (activeTab) { + case "gallery": + return "用镜头记录世界的美好瞬间,每一张照片都是时光的诗篇" + case "timeline": + return "按时间顺序回顾摄影创作历程,见证技艺与视角的成长轨迹" + case "about": + return "分享我的摄影故事,探索光影背后的创作理念与人生感悟" + case "contact": + return "期待与您合作,共同创造独特而珍贵的视觉记忆" + default: + return "用镜头记录世界的美好瞬间,每一张照片都是时光的诗篇" + } + } + + if (isLoading) { + return + } + + return ( +
+ + +
+ {(activeTab === "gallery" || activeTab === "timeline") && ( +
+

{getPageTitle()}

+

{getPageDescription()}

+
+ )} + + {activeTab === "gallery" && ( + <> + + + + )} + + {activeTab === "timeline" && } + + {activeTab === "about" && } + + {activeTab === "contact" && } +
+ + {selectedPhoto && ( + + )} +
+ ) +} diff --git a/ui/components.json b/ui/components.json new file mode 100644 index 0000000..d9ef0ae --- /dev/null +++ b/ui/components.json @@ -0,0 +1,21 @@ +{ + "$schema": "https://ui.shadcn.com/schema.json", + "style": "default", + "rsc": true, + "tsx": true, + "tailwind": { + "config": "tailwind.config.ts", + "css": "app/globals.css", + "baseColor": "neutral", + "cssVariables": true, + "prefix": "" + }, + "aliases": { + "components": "@/components", + "utils": "@/lib/utils", + "ui": "@/components/ui", + "lib": "@/lib", + "hooks": "@/hooks" + }, + "iconLibrary": "lucide" +} \ No newline at end of file diff --git a/ui/components/about-view.tsx b/ui/components/about-view.tsx new file mode 100644 index 0000000..b398f2b --- /dev/null +++ b/ui/components/about-view.tsx @@ -0,0 +1,248 @@ +"use client" + +import Image from "next/image" +import { Card, CardContent } from "@/components/ui/card" +import { Badge } from "@/components/ui/badge" +import { Button } from "@/components/ui/button" +import { Camera, Award, MapPin, Calendar, Heart, Lightbulb, Target, Users } from "lucide-react" + +interface AboutViewProps { + onContactClick?: () => void +} + +export function AboutView({ onContactClick }: AboutViewProps) { + const achievements = [ + { + year: "2024", + title: "国际摄影大赛金奖", + description: "风光摄影类别获得金奖", + icon: Award, + }, + { + year: "2023", + title: "个人摄影展", + description: "在北京798艺术区举办个人摄影展", + icon: Camera, + }, + { + year: "2022", + title: "摄影师认证", + description: "获得国际摄影师协会认证", + icon: Badge, + }, + { + year: "2021", + title: "开始职业摄影", + description: "正式成为职业摄影师", + icon: Calendar, + }, + ] + + const skills = [ + { name: "风光摄影", level: 95 }, + { name: "人像摄影", level: 90 }, + { name: "街头摄影", level: 85 }, + { name: "建筑摄影", level: 88 }, + { name: "后期处理", level: 92 }, + { name: "商业摄影", level: 80 }, + ] + + const equipment = [ + { + category: "相机机身", + items: ["Canon EOS R5", "Sony A7R IV", "Nikon D850", "Fujifilm X-T4"], + }, + { + category: "镜头", + items: ["24-70mm f/2.8", "70-200mm f/4", "85mm f/1.4", "16-35mm f/2.8", "90mm f/2.8 Macro"], + }, + { + category: "配件", + items: ["三脚架", "滤镜系统", "闪光灯", "反光板", "无人机"], + }, + ] + + return ( +
+ {/* Hero Section */} +
+

关于我

+

分享我的摄影故事,探索光影背后的创作理念与人生感悟

+
+ + {/* Personal Introduction */} +
+
+
+

张明华

+

+ 我是一名专业摄影师,拥有超过8年的摄影经验。我的作品涵盖风光、人像、街头、建筑等多个领域,致力于通过镜头捕捉世界的美好瞬间。 +

+

+ 摄影对我来说不仅仅是一份职业,更是一种表达情感和观察世界的方式。我相信每一张照片都有其独特的故事,每一次快门的按下都是对时光的珍贵记录。 +

+

+ 我的作品曾在多个国际摄影比赛中获奖,并在国内外多个城市举办过个人摄影展。我希望通过我的镜头,让更多人感受到这个世界的美好与温暖。 +

+
+ +
+
+ + 北京,中国 +
+
+ + 8年摄影经验 +
+
+ + 专业摄影师 +
+
+
+ +
+
+ 摄影师张明华 +
+
+
+ + {/* Photography Philosophy */} +
+
+

摄影理念

+

我的摄影理念建立在对光影、情感和故事的深度理解之上

+
+ +
+
+
+ +
+

情感共鸣

+

+ 每一张照片都应该能够触动观者的内心,传达真实的情感和故事。我追求的不仅是技术的完美,更是情感的真实表达。 +

+
+ +
+
+ +
+

创意视角

+

+ 我相信创意来源于对生活的细致观察和独特思考。通过不同的角度和构图,发现平凡中的不平凡。 +

+
+ +
+
+ +
+

精益求精

+

+ 从前期拍摄到后期处理,我对每一个细节都精益求精。技术是表达创意的工具,而完美的技术服务于完美的创意。 +

+
+
+
+ + {/* Skills */} +
+

专业技能

+
+ {skills.map((skill) => ( +
+
+ {skill.name} + {skill.level}% +
+
+
+
+
+ ))} +
+
+ + {/* Achievements Timeline */} +
+

成就历程

+
+
+ +
+ {achievements.map((achievement, index) => ( +
+
+ +
+ + +
+
+ +
+
+
{achievement.year}
+

{achievement.title}

+

{achievement.description}

+
+
+
+
+
+
+ ))} +
+
+
+ + {/* Equipment */} +
+

摄影设备

+
+ {equipment.map((category) => ( + + +

{category.category}

+
+ {category.items.map((item) => ( +
+
+ {item} +
+ ))} +
+
+
+ ))} +
+
+ + {/* Call to Action */} +
+ +

让我们一起创作

+

+ 如果您对我的作品感兴趣,或者有任何摄影项目需要合作,欢迎随时与我联系。我期待与您一起创造独特而珍贵的视觉记忆。 +

+ +
+
+ ) +} diff --git a/ui/components/contact-view.tsx b/ui/components/contact-view.tsx new file mode 100644 index 0000000..e9c199f --- /dev/null +++ b/ui/components/contact-view.tsx @@ -0,0 +1,432 @@ +"use client" + +import type React from "react" + +import { useState } from "react" +import { Card, CardContent } from "@/components/ui/card" +import { Button } from "@/components/ui/button" +import { Input } from "@/components/ui/input" +import { Textarea } from "@/components/ui/textarea" +import { + Mail, + Phone, + MapPin, + Clock, + Send, + CheckCircle, + Instagram, + Twitter, + Linkedin, + Camera, + Users, + Heart, + Star, + MessageCircle, +} from "lucide-react" + +export function ContactView() { + const [formData, setFormData] = useState({ + name: "", + email: "", + phone: "", + service: "", + message: "", + }) + const [isSubmitting, setIsSubmitting] = useState(false) + const [isSubmitted, setIsSubmitted] = useState(false) + + const handleInputChange = (e: React.ChangeEvent) => { + const { name, value } = e.target + setFormData((prev) => ({ ...prev, [name]: value })) + } + + const handleSubmit = async (e: React.FormEvent) => { + e.preventDefault() + setIsSubmitting(true) + + // Simulate form submission + await new Promise((resolve) => setTimeout(resolve, 2000)) + + setIsSubmitting(false) + setIsSubmitted(true) + + // Reset form after 3 seconds + setTimeout(() => { + setIsSubmitted(false) + setFormData({ + name: "", + email: "", + phone: "", + service: "", + message: "", + }) + }, 3000) + } + + const services = [ + { + title: "人像摄影", + description: "个人写真、情侣照、家庭照", + price: "¥800-2000/次", + icon: Users, + features: ["专业化妆", "多套服装", "精修10张", "原片全送"], + }, + { + title: "婚礼摄影", + description: "婚礼全程跟拍记录", + price: "¥3000-8000/天", + icon: Heart, + features: ["双机位拍摄", "全天跟拍", "精修50张", "婚礼相册"], + }, + { + title: "商业摄影", + description: "产品拍摄、企业宣传", + price: "¥1500-5000/次", + icon: Camera, + features: ["产品精修", "多角度拍摄", "商用授权", "快速交付"], + }, + { + title: "活动摄影", + description: "会议、庆典、聚会拍摄", + price: "¥1000-3000/次", + icon: Star, + features: ["现场抓拍", "关键时刻", "快速出片", "团队合影"], + }, + ] + + const contactInfo = [ + { + icon: Mail, + label: "邮箱", + value: "zhang.minghua@email.com", + link: "mailto:zhang.minghua@email.com", + }, + { + icon: Phone, + label: "电话", + value: "+86 138 0000 0000", + link: "tel:+8613800000000", + }, + { + icon: MapPin, + label: "地址", + value: "北京市朝阳区798艺术区", + link: "https://maps.google.com", + }, + { + icon: Clock, + label: "工作时间", + value: "周一至周日 9:00-21:00", + link: null, + }, + ] + + const socialLinks = [ + { icon: Instagram, label: "Instagram", link: "https://instagram.com" }, + { icon: Twitter, label: "微博", link: "https://weibo.com" }, + { icon: Linkedin, label: "LinkedIn", link: "https://linkedin.com" }, + ] + + const workflowSteps = [ + { + step: "01", + title: "初步沟通", + description: "了解您的需求和想法,确定拍摄风格和时间", + }, + { + step: "02", + title: "方案制定", + description: "制定详细的拍摄方案,包括地点、服装、道具等", + }, + { + step: "03", + title: "正式拍摄", + description: "按照方案进行专业拍摄,确保每个细节完美", + }, + { + step: "04", + title: "后期制作", + description: "精心后期处理,呈现最佳视觉效果", + }, + { + step: "05", + title: "作品交付", + description: "按时交付高质量的最终作品", + }, + ] + + return ( +
+ {/* Hero Section */} +
+

联系合作

+

期待与您合作,共同创造独特而珍贵的视觉记忆

+
+ + {/* Contact Form and Info */} +
+ {/* Contact Form */} +
+

发送消息

+ + + {!isSubmitted ? ( +
+
+
+ + +
+
+ + +
+
+ +
+ + +
+ +
+ + +
+ +
+ +