feat: 添加 AoyagiReisho 书法字体并优化表单反馈

- 使用 next/font/local 加载 AoyagiReisho.ttf 字体
- 为标题红色高亮文字应用书法字体样式
- 优化联系表单提交反馈,添加成功/失败提示
- 修复 section 参数滚动定位的时序问题
This commit is contained in:
张翔
2026-04-21 11:18:29 +08:00
parent 2fc1a586f8
commit 933a831ab3
9 changed files with 52 additions and 34 deletions
+10 -18
View File
@@ -50,7 +50,6 @@ function ContactFormContent() {
});
const [errors, setErrors] = useState<FormErrors>({});
const sectionRef = useRef<HTMLElement>(null);
const hasProcessedSuccess = useRef(isSuccessFromRedirect);
useEffect(() => {
requestAnimationFrame(() => {
@@ -58,13 +57,6 @@ function ContactFormContent() {
});
}, []);
useEffect(() => {
if (isSuccessFromRedirect && !hasProcessedSuccess.current) {
hasProcessedSuccess.current = true;
window.history.replaceState({}, '', '/contact');
}
}, [isSuccessFromRedirect]);
const validateField = (field: keyof ContactFormData, value: string) => {
try {
contactFormSchema.shape[field].parse(value);
@@ -106,8 +98,9 @@ function ContactFormContent() {
}
setIsSubmitting(true);
try {
const formEndpoint = `https://formsubmit.co/${COMPANY_INFO.email}`;
const formEndpoint = `https://formsubmit.co/ajax/${COMPANY_INFO.email}`;
const formBody = new URLSearchParams();
formBody.append('name', formData.name);
formBody.append('phone', formData.phone);
@@ -117,31 +110,30 @@ function ContactFormContent() {
formBody.append('_subject', `网站留言: ${formData.subject}`);
formBody.append('_captcha', 'false');
formBody.append('_template', 'table');
formBody.append('_next', `${window.location.origin}/contact?success=true`);
const response = await fetch(formEndpoint, {
method: 'POST',
headers: { 'Accept': 'application/json' },
body: formBody,
});
const data = await response.json();
if (response.ok && data.success === 'true') {
setIsSubmitted(true);
if (response.ok && (data.success === 'true' || data.success === true)) {
setToastMessage('表单提交成功!我们会尽快与您联系。');
setToastType('success');
setShowToast(true);
setIsSubmitted(true);
setFormData({ name: '', phone: '', email: '', subject: '', message: '' });
setErrors({});
} else {
const errorMsg = data.message || '提交失败,请稍后重试或直接发送邮件联系我们。';
if (errorMsg.includes('HTML files') || errorMsg.includes('web server')) {
setToastMessage('表单服务需要在生产环境激活。部署后首次提交会发送确认邮件到 ' + COMPANY_INFO.email);
setToastType('error');
} else {
setToastMessage(errorMsg);
setToastType('error');
}
setToastType('error');
setShowToast(true);
}
} catch {
@@ -180,7 +172,7 @@ function ContactFormContent() {
<span className="text-sm text-[#5C5C5C] tracking-wide" data-testid="page-badge"></span>
</div>
<h1 className="text-4xl md:text-5xl font-bold text-[#1C1C1C] mb-4">
<span className="text-[#C41E3A]"></span>
<span className="text-[#C41E3A] font-calligraphy"></span>
</h1>
<p className="mt-4 text-[#5C5C5C] max-w-2xl" data-testid="page-description">
+25 -11
View File
@@ -51,17 +51,31 @@ function HomeContent() {
useEffect(() => {
const section = searchParams.get('section');
if (section) {
const timer = setTimeout(() => {
const targetElement = document.getElementById(section);
if (targetElement) {
targetElement.scrollIntoView({ behavior: 'smooth', block: 'start' });
}
}, 100);
return () => clearTimeout(timer);
}
return undefined;
if (!section) {return;}
const maxAttempts = 50;
const interval = 100;
let attempts = 0;
const scrollToSection = () => {
const targetElement = document.getElementById(section);
if (targetElement) {
targetElement.scrollIntoView({ behavior: 'smooth', block: 'start' });
return true;
}
return false;
};
if (scrollToSection()) {return;}
const timer = setInterval(() => {
attempts++;
if (scrollToSection() || attempts >= maxAttempts) {
clearInterval(timer);
}
}, interval);
return () => clearInterval(timer);
}, [searchParams]);
return (
Binary file not shown.
+4
View File
@@ -19,6 +19,10 @@
font-family: 'Aoyagi Reisho', 'STKaiti', 'KaiTi', serif;
}
.font-calligraphy {
font-family: var(--font-aoyagi-reisho), 'STKaiti', 'KaiTi', serif !important;
}
@theme inline {
--font-sans: var(--font-geist-sans);
--font-mono: var(--font-geist-mono);
+9 -1
View File
@@ -1,5 +1,6 @@
import type { Metadata, Viewport } from "next";
import { Geist, Geist_Mono, Noto_Sans_SC, Ma_Shan_Zheng, Long_Cang } from "next/font/google";
import localFont from "next/font/local";
import "./globals.css";
import { ThemeProvider } from "@/contexts/theme-context";
import { GoogleAnalytics } from "@/components/analytics/GoogleAnalytics";
@@ -47,6 +48,13 @@ const longCang = Long_Cang({
preload: false,
});
const aoyagiReisho = localFont({
src: "./fonts/AoyagiReisho.ttf",
variable: "--font-aoyagi-reisho",
display: "swap",
preload: true,
});
export const metadata: Metadata = {
title: {
default: "四川睿新致远科技有限公司 - 企业数字化转型服务商",
@@ -130,7 +138,7 @@ export default function RootLayout({
<WebsiteSchema />
</head>
<body
className={`${geistSans.variable} ${geistMono.variable} ${notoSansSC.variable} ${maShanZheng.variable} ${longCang.variable} font-sans antialiased`}
className={`${geistSans.variable} ${geistMono.variable} ${notoSansSC.variable} ${maShanZheng.variable} ${longCang.variable} ${aoyagiReisho.variable} font-sans antialiased`}
style={{ fontFamily: "'Noto Sans SC', 'Geist', -apple-system, BlinkMacSystemFont, sans-serif" }}
>
<ScrollProgress />