's'
This commit is contained in:
@@ -141,6 +141,8 @@ export default function JoinPage() {
|
|||||||
const [fromVolunteer, setFromVolunteer] = useState(false);
|
const [fromVolunteer, setFromVolunteer] = useState(false);
|
||||||
const [paying, setPaying] = useState(false);
|
const [paying, setPaying] = useState(false);
|
||||||
const initialWechatCheckDone = useRef(false);
|
const initialWechatCheckDone = useRef(false);
|
||||||
|
const lastSubmitTime = useRef(0);
|
||||||
|
const SUBMIT_THROTTLE_MS = 2000;
|
||||||
|
|
||||||
const fetchByWechat = async (w: string) => {
|
const fetchByWechat = async (w: string) => {
|
||||||
if (!w.trim()) return;
|
if (!w.trim()) return;
|
||||||
@@ -243,6 +245,26 @@ export default function JoinPage() {
|
|||||||
const handleSubmit = async (e: FormEvent) => {
|
const handleSubmit = async (e: FormEvent) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
setError(null);
|
setError(null);
|
||||||
|
|
||||||
|
const now = Date.now();
|
||||||
|
if (now - lastSubmitTime.current < SUBMIT_THROTTLE_MS) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (userRecord?.hasRecord) {
|
||||||
|
setError("该微信号已报名,请勿重复提交");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
const checkRes = await fetch(`/api/join/by-wechat?wechat_id=${encodeURIComponent(wechat.trim())}`, { cache: "no-store" });
|
||||||
|
const checkData = await checkRes.json();
|
||||||
|
if (checkData?.hasRecord) {
|
||||||
|
setError("该微信号已报名,请勿重复提交");
|
||||||
|
fetchByWechat(wechat.trim());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
/* 校验失败时继续提交,由后端兜底 */
|
||||||
|
}
|
||||||
if (xiaohongshuUrl.trim() && urlError) {
|
if (xiaohongshuUrl.trim() && urlError) {
|
||||||
setError("请先修正小红书链接");
|
setError("请先修正小红书链接");
|
||||||
return;
|
return;
|
||||||
@@ -263,6 +285,7 @@ export default function JoinPage() {
|
|||||||
setError("请选择性别");
|
setError("请选择性别");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
lastSubmitTime.current = now;
|
||||||
setSubmitting(true);
|
setSubmitting(true);
|
||||||
try {
|
try {
|
||||||
const formGenderFemale = gender === "女" || gender === "female";
|
const formGenderFemale = gender === "女" || gender === "female";
|
||||||
|
|||||||
@@ -2,6 +2,18 @@ import type { NextConfig } from "next";
|
|||||||
|
|
||||||
const nextConfig: NextConfig = {
|
const nextConfig: NextConfig = {
|
||||||
reactStrictMode: true,
|
reactStrictMode: true,
|
||||||
|
async headers() {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
source: "/:path*",
|
||||||
|
headers: [
|
||||||
|
{ key: "Cache-Control", value: "no-store, no-cache, must-revalidate, proxy-revalidate" },
|
||||||
|
{ key: "Pragma", value: "no-cache" },
|
||||||
|
{ key: "Expires", value: "0" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
},
|
||||||
images: {
|
images: {
|
||||||
remotePatterns: [
|
remotePatterns: [
|
||||||
{ protocol: "https", hostname: "picsum.photos", pathname: "/**" },
|
{ protocol: "https", hostname: "picsum.photos", pathname: "/**" },
|
||||||
|
|||||||
Reference in New Issue
Block a user