feat: 添加面包屑导航组件并优化页面布局

refactor: 重构页面结构和导航逻辑

fix: 修复移动端菜单导航和滚动行为

perf: 优化图片加载性能和资源请求

test: 添加端到端测试和性能测试用例

docs: 更新.gitignore文件

chore: 更新依赖和配置

style: 优化代码格式和类型安全

ci: 调整Playwright测试超时时间

build: 更新Next.js配置和构建选项
This commit is contained in:
张翔
2026-02-28 09:09:04 +08:00
parent 9d01e0982f
commit 9451814ca4
60 changed files with 4078 additions and 148 deletions
+220 -2
View File
@@ -1,10 +1,14 @@
import { NextRequest, NextResponse } from 'next/server';
import { Resend } from 'resend';
const resend = new Resend(process.env.RESEND_API_KEY);
const companyEmail = process.env.COMPANY_EMAIL || 'contact@novalon.cn';
export async function POST(request: NextRequest) {
try {
const body = await request.json();
const { name, email, phone, subject, message } = body;
const { name, email, phone, subject, message, website, submitTime, mathHash, mathTimestamp, mathAnswer } = body;
if (!name || !email || !subject || !message) {
return NextResponse.json(
@@ -21,8 +25,222 @@ export async function POST(request: NextRequest) {
);
}
if (website) {
console.log('Honeypot field filled, rejecting request');
return NextResponse.json(
{ success: true, message: '消息已发送' },
{ status: 200 }
);
}
if (submitTime) {
const timeDiff = Date.now() - parseInt(submitTime);
if (timeDiff < 2000) {
console.log('Submission too fast:', timeDiff);
return NextResponse.json(
{ success: false, error: '提交过快,请稍后再试' },
{ status: 400 }
);
}
}
if (mathHash && mathTimestamp && mathAnswer !== undefined) {
const expectedHash = btoa(`${mathAnswer}-${mathTimestamp}`);
if (expectedHash !== mathHash) {
console.log('Invalid math captcha');
return NextResponse.json(
{ success: false, error: '验证码错误,请重新计算' },
{ status: 400 }
);
}
}
const emailContent = `
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', sans-serif;
line-height: 1.6;
color: #1C1C1C;
margin: 0;
padding: 0;
background-color: #f5f5f5;
}
.container {
max-width: 600px;
margin: 0 auto;
padding: 20px;
background-color: #ffffff;
}
.header {
background: #C41E3A;
color: white;
padding: 40px 30px;
text-align: center;
border-radius: 8px 8px 0 0;
}
.header h1 {
margin: 0;
font-size: 28px;
font-weight: 600;
}
.header p {
margin: 10px 0 0 0;
font-size: 14px;
opacity: 0.9;
}
.content {
padding: 40px 30px;
background: #ffffff;
}
.info-card {
background: #f9f9f9;
border-radius: 8px;
padding: 20px;
margin-bottom: 25px;
border: 1px solid #e5e5e5;
}
.info-row {
display: flex;
margin-bottom: 12px;
align-items: flex-start;
}
.info-row:last-child {
margin-bottom: 0;
}
.info-label {
font-weight: 600;
color: #1C1C1C;
min-width: 70px;
font-size: 14px;
}
.info-value {
color: #5C5C5C;
font-size: 14px;
flex: 1;
}
.message-box {
background: #fff;
padding: 20px;
border-left: 4px solid #C41E3A;
margin-top: 20px;
border-radius: 0 8px 8px 0;
box-shadow: 0 2px 8px rgba(0,0,0,0.05);
}
.message-label {
font-weight: 600;
color: #C41E3A;
font-size: 14px;
margin-bottom: 10px;
}
.message-content {
color: #1C1C1C;
font-size: 14px;
line-height: 1.8;
white-space: pre-wrap;
}
.footer {
text-align: center;
padding: 30px;
color: #8C8C8C;
font-size: 12px;
border-top: 1px solid #e5e5e5;
}
.footer a {
color: #C41E3A;
text-decoration: none;
}
.divider {
height: 1px;
background: #e5e5e5;
margin: 25px 0;
}
.badge {
display: inline-block;
background: #C41E3A;
color: white;
padding: 4px 12px;
border-radius: 12px;
font-size: 12px;
margin-bottom: 10px;
}
</style>
</head>
<body>
<div class="container">
<div class="header">
<h1>📬 新的客户咨询</h1>
<p>来自 睿新致远官方网站</p>
</div>
<div class="content">
<span class="badge">新消息</span>
<div class="info-card">
<div class="info-row">
<div class="info-label">姓名</div>
<div class="info-value">${name}</div>
</div>
<div class="info-row">
<div class="info-label">邮箱</div>
<div class="info-value"><a href="mailto:${email}" style="color: #C41E3A; text-decoration: none;">${email}</a></div>
</div>
${phone ? `
<div class="info-row">
<div class="info-label">电话</div>
<div class="info-value">${phone}</div>
</div>
` : ''}
<div class="info-row">
<div class="info-label">主题</div>
<div class="info-value">${subject}</div>
</div>
</div>
<div class="message-box">
<div class="message-label">咨询内容</div>
<div class="message-content">${message}</div>
</div>
<div class="divider"></div>
<div style="text-align: center; color: #8C8C8C; font-size: 13px;">
<p>💡 提示:点击邮箱地址可直接回复客户</p>
</div>
</div>
<div class="footer">
<p style="margin-bottom: 10px;">本邮件由 睿新致远 官网联系表单自动发送,请勿直接回复此邮件</p>
<p style="margin-bottom: 10px;">如需回复客户,请点击上方邮箱地址或直接回复客户的原始邮件</p>
<p style="margin-bottom: 15px;">提交时间:${new Date().toLocaleString('zh-CN', { timeZone: 'Asia/Shanghai', year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit' })}</p>
<p style="margin-top: 15px; border-top: 1px solid #e5e5e5; padding-top: 15px;">© ${new Date().getFullYear()} 四川睿新致远科技有限公司. All rights reserved.</p>
</div>
</div>
</body>
</html>
`;
const { data, error } = await resend.emails.send({
from: '睿新致远官网 <onboarding@resend.dev>',
to: [companyEmail],
subject: `📧 ${subject} - ${name}`,
html: emailContent,
replyTo: email,
});
if (error) {
console.error('Resend API error:', error);
return NextResponse.json(
{ success: false, error: '邮件发送失败,请稍后重试' },
{ status: 500 }
);
}
console.log('Email sent successfully:', data);
return NextResponse.json({ success: true, message: '消息已发送' });
} catch (error) {
console.error('Contact form submission error:', error);
return NextResponse.json(
{ success: false, error: '提交失败,请重试' },
{ status: 500 }