feat: 添加连锁门店系统首页及核心UI组件

新增首页布局、导航栏、页脚及多个核心UI组件(按钮、卡片、表格等)
添加图片资源、工具函数和样式配置
实现响应式设计和主题支持
包含行业解决方案展示区块
This commit is contained in:
JanYork
2026-03-18 10:50:42 +08:00
commit 6a68a96287
110 changed files with 12842 additions and 0 deletions

View File

@@ -0,0 +1,154 @@
"use client"
import { useState } from "react"
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 { SectionReveal } from "@/components/ui/section-reveal"
import { Phone, Mail, MapPin, Clock3, ArrowRight, CheckCircle2 } from "lucide-react"
import homeData from "@/data/home.json"
const iconMap: Record<string, React.ReactNode> = {
phone: <Phone className="w-5 h-5" />,
mail: <Mail className="w-5 h-5" />,
mappin: <MapPin className="w-5 h-5" />,
clock: <Clock3 className="w-5 h-5" />,
}
export function ContactSection() {
const { contact } = homeData
const sectionBadge = (contact as any).sectionBadge ?? (contact as any).sectionTag
const info = ((contact as any).info ??
((contact as any).infoItems ?? []).map((item: any) => ({
...item,
icon: String(item.icon ?? "").toLowerCase(),
sub: item.sub ?? "",
}))) as Array<{ icon: string; label: string; value: string; sub?: string }>
const submitLabel = (contact.form as any).submitLabel ?? (contact.form as any).submit
const [submitted, setSubmitted] = useState(false)
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault()
setSubmitted(true)
}
return (
<section id="contact" className="section-panel bg-background">
<SectionReveal className="w-full max-w-7xl mx-auto px-4 sm:px-6 lg:px-8" delay={140}>
{/* Header */}
<div className="text-center max-w-2xl mx-auto mb-16">
<Badge variant="secondary" className="mb-4 text-primary border-primary/20 bg-primary/8 px-3 py-1">
{sectionBadge}
</Badge>
<h2 className="text-3xl sm:text-4xl lg:text-5xl font-extrabold text-foreground text-balance tracking-tight mb-4">
{contact.title}
</h2>
<p className="text-muted-foreground text-lg leading-relaxed text-pretty">
{contact.subtitle}
</p>
</div>
<div className="grid lg:grid-cols-5 gap-10 items-start">
{/* Left: info */}
<div className="lg:col-span-2 flex flex-col gap-5">
{info.map((item) => (
<div
key={item.label}
className="flex items-start gap-4 p-5 bg-muted rounded-2xl border border-border hover:border-primary/30 transition-colors"
>
<div className="w-11 h-11 rounded-xl bg-primary/10 text-primary flex items-center justify-center shrink-0">
{iconMap[item.icon] ?? iconMap.phone}
</div>
<div>
<p className="text-xs font-semibold text-muted-foreground uppercase tracking-widest mb-1">{item.label}</p>
<p className="font-bold text-foreground text-sm">{item.value}</p>
<p className="text-xs text-muted-foreground mt-0.5">{item.sub}</p>
</div>
</div>
))}
{/* Trust note */}
<div className="bg-primary/6 border border-primary/15 rounded-2xl p-5">
<p className="text-sm text-primary font-semibold mb-1.5"></p>
<p className="text-xs text-muted-foreground leading-relaxed">
{" "}
<strong className="text-foreground">2 </strong>
{" "}
</p>
</div>
</div>
{/* Right: form */}
<div className="lg:col-span-3 bg-white border border-border rounded-3xl p-8 shadow-lg shadow-primary/5">
{submitted ? (
<div className="flex flex-col items-center justify-center py-16 gap-5 text-center">
<div className="w-16 h-16 rounded-full bg-green-50 border-2 border-green-200 flex items-center justify-center">
<CheckCircle2 className="w-8 h-8 text-green-500" />
</div>
<div>
<h3 className="text-xl font-bold text-foreground mb-2"></h3>
<p className="text-muted-foreground text-sm">
2
</p>
</div>
<Button variant="outline" onClick={() => setSubmitted(false)} className="mt-2">
</Button>
</div>
) : (
<form onSubmit={handleSubmit} className="flex flex-col gap-5" noValidate>
<h3 className="text-lg font-bold text-foreground"></h3>
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
<div className="flex flex-col gap-1.5">
<label className="text-xs font-medium text-muted-foreground" htmlFor="name"></label>
<Input id="name" placeholder={contact.form.namePlaceholder} required className="h-11" />
</div>
<div className="flex flex-col gap-1.5">
<label className="text-xs font-medium text-muted-foreground" htmlFor="company"> / </label>
<Input id="company" placeholder={contact.form.companyPlaceholder} required className="h-11" />
</div>
<div className="flex flex-col gap-1.5">
<label className="text-xs font-medium text-muted-foreground" htmlFor="phone"></label>
<Input id="phone" type="tel" placeholder={contact.form.phonePlaceholder} required className="h-11" />
</div>
<div className="flex flex-col gap-1.5">
<label className="text-xs font-medium text-muted-foreground" htmlFor="scale"></label>
<Input id="scale" placeholder={contact.form.scalePlaceholder} className="h-11" />
</div>
</div>
<div className="flex flex-col gap-1.5">
<label className="text-xs font-medium text-muted-foreground" htmlFor="message"></label>
<Textarea
id="message"
placeholder={contact.form.messagePlaceholder}
rows={4}
className="resize-none"
/>
</div>
<Button
type="submit"
size="lg"
className="w-full bg-primary hover:bg-primary-dark text-white h-12 text-base font-semibold group shadow-lg shadow-primary/25"
>
<span className="flex items-center gap-2">
{submitLabel}
<ArrowRight className="w-4 h-4 group-hover:translate-x-0.5 transition-transform" />
</span>
</Button>
<p className="text-xs text-muted-foreground text-center">
{" "}
<span className="text-primary cursor-pointer hover:underline"></span>
</p>
</form>
)}
</div>
</div>
</SectionReveal>
</section>
)
}