feat: 添加 AoyagiReisho 书法字体并优化表单反馈
- 使用 next/font/local 加载 AoyagiReisho.ttf 字体 - 为标题红色高亮文字应用书法字体样式 - 优化联系表单提交反馈,添加成功/失败提示 - 修复 section 参数滚动定位的时序问题
This commit is contained in:
@@ -50,7 +50,6 @@ function ContactFormContent() {
|
|||||||
});
|
});
|
||||||
const [errors, setErrors] = useState<FormErrors>({});
|
const [errors, setErrors] = useState<FormErrors>({});
|
||||||
const sectionRef = useRef<HTMLElement>(null);
|
const sectionRef = useRef<HTMLElement>(null);
|
||||||
const hasProcessedSuccess = useRef(isSuccessFromRedirect);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
requestAnimationFrame(() => {
|
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) => {
|
const validateField = (field: keyof ContactFormData, value: string) => {
|
||||||
try {
|
try {
|
||||||
contactFormSchema.shape[field].parse(value);
|
contactFormSchema.shape[field].parse(value);
|
||||||
@@ -106,8 +98,9 @@ function ContactFormContent() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
setIsSubmitting(true);
|
setIsSubmitting(true);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const formEndpoint = `https://formsubmit.co/${COMPANY_INFO.email}`;
|
const formEndpoint = `https://formsubmit.co/ajax/${COMPANY_INFO.email}`;
|
||||||
const formBody = new URLSearchParams();
|
const formBody = new URLSearchParams();
|
||||||
formBody.append('name', formData.name);
|
formBody.append('name', formData.name);
|
||||||
formBody.append('phone', formData.phone);
|
formBody.append('phone', formData.phone);
|
||||||
@@ -117,31 +110,30 @@ function ContactFormContent() {
|
|||||||
formBody.append('_subject', `网站留言: ${formData.subject}`);
|
formBody.append('_subject', `网站留言: ${formData.subject}`);
|
||||||
formBody.append('_captcha', 'false');
|
formBody.append('_captcha', 'false');
|
||||||
formBody.append('_template', 'table');
|
formBody.append('_template', 'table');
|
||||||
formBody.append('_next', `${window.location.origin}/contact?success=true`);
|
|
||||||
|
|
||||||
const response = await fetch(formEndpoint, {
|
const response = await fetch(formEndpoint, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: { 'Accept': 'application/json' },
|
headers: { 'Accept': 'application/json' },
|
||||||
body: formBody,
|
body: formBody,
|
||||||
});
|
});
|
||||||
|
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
|
|
||||||
if (response.ok && data.success === 'true') {
|
if (response.ok && (data.success === 'true' || data.success === true)) {
|
||||||
setIsSubmitted(true);
|
|
||||||
setToastMessage('表单提交成功!我们会尽快与您联系。');
|
setToastMessage('表单提交成功!我们会尽快与您联系。');
|
||||||
setToastType('success');
|
setToastType('success');
|
||||||
setShowToast(true);
|
setShowToast(true);
|
||||||
|
setIsSubmitted(true);
|
||||||
setFormData({ name: '', phone: '', email: '', subject: '', message: '' });
|
setFormData({ name: '', phone: '', email: '', subject: '', message: '' });
|
||||||
|
setErrors({});
|
||||||
} else {
|
} else {
|
||||||
const errorMsg = data.message || '提交失败,请稍后重试或直接发送邮件联系我们。';
|
const errorMsg = data.message || '提交失败,请稍后重试或直接发送邮件联系我们。';
|
||||||
if (errorMsg.includes('HTML files') || errorMsg.includes('web server')) {
|
if (errorMsg.includes('HTML files') || errorMsg.includes('web server')) {
|
||||||
setToastMessage('表单服务需要在生产环境激活。部署后首次提交会发送确认邮件到 ' + COMPANY_INFO.email);
|
setToastMessage('表单服务需要在生产环境激活。部署后首次提交会发送确认邮件到 ' + COMPANY_INFO.email);
|
||||||
setToastType('error');
|
|
||||||
} else {
|
} else {
|
||||||
setToastMessage(errorMsg);
|
setToastMessage(errorMsg);
|
||||||
setToastType('error');
|
|
||||||
}
|
}
|
||||||
|
setToastType('error');
|
||||||
setShowToast(true);
|
setShowToast(true);
|
||||||
}
|
}
|
||||||
} catch {
|
} catch {
|
||||||
@@ -180,7 +172,7 @@ function ContactFormContent() {
|
|||||||
<span className="text-sm text-[#5C5C5C] tracking-wide" data-testid="page-badge">联系我们</span>
|
<span className="text-sm text-[#5C5C5C] tracking-wide" data-testid="page-badge">联系我们</span>
|
||||||
</div>
|
</div>
|
||||||
<h1 className="text-4xl md:text-5xl font-bold text-[#1C1C1C] mb-4">
|
<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>
|
</h1>
|
||||||
<p className="mt-4 text-[#5C5C5C] max-w-2xl" data-testid="page-description">
|
<p className="mt-4 text-[#5C5C5C] max-w-2xl" data-testid="page-description">
|
||||||
无论您有任何问题或合作意向,我们都很乐意与您交流
|
无论您有任何问题或合作意向,我们都很乐意与您交流
|
||||||
|
|||||||
@@ -51,17 +51,31 @@ function HomeContent() {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const section = searchParams.get('section');
|
const section = searchParams.get('section');
|
||||||
if (section) {
|
if (!section) {return;}
|
||||||
const timer = setTimeout(() => {
|
|
||||||
const targetElement = document.getElementById(section);
|
const maxAttempts = 50;
|
||||||
if (targetElement) {
|
const interval = 100;
|
||||||
targetElement.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
let attempts = 0;
|
||||||
}
|
|
||||||
}, 100);
|
const scrollToSection = () => {
|
||||||
|
const targetElement = document.getElementById(section);
|
||||||
return () => clearTimeout(timer);
|
if (targetElement) {
|
||||||
}
|
targetElement.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
||||||
return undefined;
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (scrollToSection()) {return;}
|
||||||
|
|
||||||
|
const timer = setInterval(() => {
|
||||||
|
attempts++;
|
||||||
|
if (scrollToSection() || attempts >= maxAttempts) {
|
||||||
|
clearInterval(timer);
|
||||||
|
}
|
||||||
|
}, interval);
|
||||||
|
|
||||||
|
return () => clearInterval(timer);
|
||||||
}, [searchParams]);
|
}, [searchParams]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
Binary file not shown.
@@ -19,6 +19,10 @@
|
|||||||
font-family: 'Aoyagi Reisho', 'STKaiti', 'KaiTi', serif;
|
font-family: 'Aoyagi Reisho', 'STKaiti', 'KaiTi', serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.font-calligraphy {
|
||||||
|
font-family: var(--font-aoyagi-reisho), 'STKaiti', 'KaiTi', serif !important;
|
||||||
|
}
|
||||||
|
|
||||||
@theme inline {
|
@theme inline {
|
||||||
--font-sans: var(--font-geist-sans);
|
--font-sans: var(--font-geist-sans);
|
||||||
--font-mono: var(--font-geist-mono);
|
--font-mono: var(--font-geist-mono);
|
||||||
|
|||||||
+9
-1
@@ -1,5 +1,6 @@
|
|||||||
import type { Metadata, Viewport } from "next";
|
import type { Metadata, Viewport } from "next";
|
||||||
import { Geist, Geist_Mono, Noto_Sans_SC, Ma_Shan_Zheng, Long_Cang } from "next/font/google";
|
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 "./globals.css";
|
||||||
import { ThemeProvider } from "@/contexts/theme-context";
|
import { ThemeProvider } from "@/contexts/theme-context";
|
||||||
import { GoogleAnalytics } from "@/components/analytics/GoogleAnalytics";
|
import { GoogleAnalytics } from "@/components/analytics/GoogleAnalytics";
|
||||||
@@ -47,6 +48,13 @@ const longCang = Long_Cang({
|
|||||||
preload: false,
|
preload: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const aoyagiReisho = localFont({
|
||||||
|
src: "./fonts/AoyagiReisho.ttf",
|
||||||
|
variable: "--font-aoyagi-reisho",
|
||||||
|
display: "swap",
|
||||||
|
preload: true,
|
||||||
|
});
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
export const metadata: Metadata = {
|
||||||
title: {
|
title: {
|
||||||
default: "四川睿新致远科技有限公司 - 企业数字化转型服务商",
|
default: "四川睿新致远科技有限公司 - 企业数字化转型服务商",
|
||||||
@@ -130,7 +138,7 @@ export default function RootLayout({
|
|||||||
<WebsiteSchema />
|
<WebsiteSchema />
|
||||||
</head>
|
</head>
|
||||||
<body
|
<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" }}
|
style={{ fontFamily: "'Noto Sans SC', 'Geist', -apple-system, BlinkMacSystemFont, sans-serif" }}
|
||||||
>
|
>
|
||||||
<ScrollProgress />
|
<ScrollProgress />
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ export function CasesSection() {
|
|||||||
className="text-center max-w-3xl mx-auto mb-16"
|
className="text-center max-w-3xl mx-auto mb-16"
|
||||||
>
|
>
|
||||||
<h2 id="cases-heading" className="text-4xl md:text-5xl font-bold text-[#1C1C1C] mb-4">
|
<h2 id="cases-heading" className="text-4xl md:text-5xl font-bold text-[#1C1C1C] mb-4">
|
||||||
与谁同行,<span className="text-[#C41E3A]">决定能走多远</span>
|
与谁同行,<span className="text-[#C41E3A] font-calligraphy">决定能走多远</span>
|
||||||
</h2>
|
</h2>
|
||||||
<p className="text-lg text-[#5C5C5C] max-w-2xl mx-auto">
|
<p className="text-lg text-[#5C5C5C] max-w-2xl mx-auto">
|
||||||
我们与优秀的企业同行,共同成长,共创未来
|
我们与优秀的企业同行,共同成长,共创未来
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ export function NewsSection() {
|
|||||||
className="text-center max-w-3xl mx-auto mb-16"
|
className="text-center max-w-3xl mx-auto mb-16"
|
||||||
>
|
>
|
||||||
<h2 id="news-heading" className="text-3xl sm:text-4xl lg:text-5xl font-bold text-[#1C1C1C] mb-6">
|
<h2 id="news-heading" className="text-3xl sm:text-4xl lg:text-5xl font-bold text-[#1C1C1C] mb-6">
|
||||||
最新<span className="text-[#C41E3A]">资讯</span>
|
最新<span className="text-[#C41E3A] font-calligraphy">资讯</span>
|
||||||
</h2>
|
</h2>
|
||||||
<p className="text-lg text-[#5C5C5C]">
|
<p className="text-lg text-[#5C5C5C]">
|
||||||
了解公司最新动态、行业资讯和技术分享
|
了解公司最新动态、行业资讯和技术分享
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ export function ProductsSection() {
|
|||||||
className="text-center max-w-3xl mx-auto mb-16"
|
className="text-center max-w-3xl mx-auto mb-16"
|
||||||
>
|
>
|
||||||
<h2 id="products-heading" className="text-4xl md:text-5xl font-bold text-[#1C1C1C] mb-6">
|
<h2 id="products-heading" className="text-4xl md:text-5xl font-bold text-[#1C1C1C] mb-6">
|
||||||
我们的<span className="text-[#C41E3A]">产品</span>
|
我们的<span className="text-[#C41E3A] font-calligraphy">产品</span>
|
||||||
</h2>
|
</h2>
|
||||||
<p className="text-lg text-[#5C5C5C]">
|
<p className="text-lg text-[#5C5C5C]">
|
||||||
自主研发的企业级产品,助力企业高效运营,实现数字化转型
|
自主研发的企业级产品,助力企业高效运营,实现数字化转型
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ export function ServicesSection() {
|
|||||||
className="text-center max-w-3xl mx-auto mb-16"
|
className="text-center max-w-3xl mx-auto mb-16"
|
||||||
>
|
>
|
||||||
<h2 id="services-heading" className="text-4xl md:text-5xl font-bold text-[#1C1C1C] mb-4">
|
<h2 id="services-heading" className="text-4xl md:text-5xl font-bold text-[#1C1C1C] mb-4">
|
||||||
我们的 <span className="text-[#C41E3A]">核心业务</span>
|
我们的 <span className="text-[#C41E3A] font-calligraphy">核心业务</span>
|
||||||
</h2>
|
</h2>
|
||||||
<p className="text-lg text-[#5C5C5C] max-w-2xl mx-auto">
|
<p className="text-lg text-[#5C5C5C] max-w-2xl mx-auto">
|
||||||
专业技术团队,为您提供全方位的数字化解决方案
|
专业技术团队,为您提供全方位的数字化解决方案
|
||||||
|
|||||||
Reference in New Issue
Block a user