's'
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
"use client";
|
||||
|
||||
import { useState, useRef, type FormEvent, type ChangeEvent } from "react";
|
||||
import { useState, useRef, useEffect, type FormEvent, type ChangeEvent } from "react";
|
||||
import { getPayEnv, getRecommendedChannel, mustUseWxPay, type PayChannel, type PayEnv } from "../lib/payEnv";
|
||||
|
||||
const genderOptions = ["男", "女"];
|
||||
const singleOptions = ["单身", "恋爱中", "已婚"];
|
||||
@@ -43,6 +44,22 @@ export default function JoinPage() {
|
||||
const [submitted, setSubmitted] = useState(false);
|
||||
const [submitting, setSubmitting] = useState(false);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const [payRedirecting, setPayRedirecting] = useState(false);
|
||||
const [payEnv, setPayEnv] = useState<PayEnv | null>(null);
|
||||
const [payChannel, setPayChannel] = useState<PayChannel>("alipay");
|
||||
|
||||
useEffect(() => {
|
||||
if (typeof window !== "undefined" && new URLSearchParams(window.location.search).get("paid") === "1") {
|
||||
setSubmitted(true);
|
||||
}
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (typeof window === "undefined") return;
|
||||
const env = getPayEnv();
|
||||
setPayEnv(env);
|
||||
setPayChannel(getRecommendedChannel(env));
|
||||
}, []);
|
||||
|
||||
const set = (key: keyof FormData, value: string) =>
|
||||
setForm((prev) => ({ ...prev, [key]: value }));
|
||||
@@ -61,7 +78,41 @@ export default function JoinPage() {
|
||||
if (!res.ok || !data?.ok) {
|
||||
throw new Error(data?.error || "提交失败,请稍后重试");
|
||||
}
|
||||
setSubmitted(true);
|
||||
const userId = data.user_id;
|
||||
if (!userId) {
|
||||
setSubmitted(true);
|
||||
return;
|
||||
}
|
||||
setSubmitting(false);
|
||||
setPayRedirecting(true);
|
||||
const returnUrl = `${window.location.origin}/join?paid=1`;
|
||||
const payForm = document.createElement("form");
|
||||
payForm.method = "POST";
|
||||
payForm.action = "/api/pay";
|
||||
payForm.target = "_self";
|
||||
payForm.style.display = "none";
|
||||
const env = getPayEnv();
|
||||
const channel = mustUseWxPay(env) ? "wxpay" : payChannel;
|
||||
const device = env === "pc" ? "pc" : "h5"; // PC 跳转 payurl,H5/微信 用 payurl/payurl2
|
||||
const fields: [string, string][] = [
|
||||
["user_id", userId],
|
||||
["total_fee", "80"],
|
||||
["type", "meetup"],
|
||||
["channel", channel],
|
||||
["device", device],
|
||||
["return_url", returnUrl],
|
||||
["html", "1"],
|
||||
];
|
||||
fields.forEach(([k, v]) => {
|
||||
const input = document.createElement("input");
|
||||
input.type = "hidden";
|
||||
input.name = k;
|
||||
input.value = v;
|
||||
payForm.appendChild(input);
|
||||
});
|
||||
document.body.appendChild(payForm);
|
||||
payForm.submit();
|
||||
return;
|
||||
} catch (err) {
|
||||
setError(err instanceof Error ? err.message : "网络错误,请重试");
|
||||
} finally {
|
||||
@@ -395,6 +446,41 @@ export default function JoinPage() {
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* ── 支付通道选择(PC/H5 可选,微信内强制微信支付)── */}
|
||||
<div className="mt-6 rounded-xl border border-slate-100 bg-slate-50/50 px-4 py-4 sm:px-5">
|
||||
<p className="mb-3 text-sm font-bold text-slate-700">💳 支付方式</p>
|
||||
{payEnv === "wechat" ? (
|
||||
<p className="text-sm text-slate-500">
|
||||
当前在微信内打开,将使用 <span className="font-medium text-emerald-600">微信支付</span>
|
||||
</p>
|
||||
) : (
|
||||
<div className="flex gap-3">
|
||||
<label className="flex flex-1 cursor-pointer items-center gap-2 rounded-lg border-2 px-4 py-3 transition-colors has-[:checked]:border-sky-500 has-[:checked]:bg-sky-50">
|
||||
<input
|
||||
type="radio"
|
||||
name="payChannel"
|
||||
value="alipay"
|
||||
checked={payChannel === "alipay"}
|
||||
onChange={() => setPayChannel("alipay")}
|
||||
className="h-4 w-4 border-slate-300 text-sky-500"
|
||||
/>
|
||||
<span className="text-sm font-medium text-slate-700">支付宝</span>
|
||||
</label>
|
||||
<label className="flex flex-1 cursor-pointer items-center gap-2 rounded-lg border-2 px-4 py-3 transition-colors has-[:checked]:border-emerald-500 has-[:checked]:bg-emerald-50">
|
||||
<input
|
||||
type="radio"
|
||||
name="payChannel"
|
||||
value="wxpay"
|
||||
checked={payChannel === "wxpay"}
|
||||
onChange={() => setPayChannel("wxpay")}
|
||||
className="h-4 w-4 border-slate-300 text-emerald-500"
|
||||
/>
|
||||
<span className="text-sm font-medium text-slate-700">微信支付</span>
|
||||
</label>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* ── Submit ── */}
|
||||
<div className="mt-8 sm:mt-10">
|
||||
{error && (
|
||||
@@ -404,15 +490,12 @@ export default function JoinPage() {
|
||||
)}
|
||||
<button
|
||||
type="submit"
|
||||
disabled={submitting || uploading}
|
||||
disabled={submitting || uploading || payRedirecting}
|
||||
className="w-full rounded-full bg-[#1aad19] py-3.5 text-lg font-semibold text-white shadow-md shadow-emerald-500/20 transition-all hover:bg-[#179b16] hover:shadow-lg hover:shadow-emerald-500/25 active:scale-[0.98] disabled:cursor-not-allowed disabled:opacity-70 sm:py-4"
|
||||
>
|
||||
{uploading ? "媒体上传中…" : submitting ? "提交中…" : "提交申请"}
|
||||
{uploading ? "媒体上传中…" : payRedirecting ? "跳转支付中…" : submitting ? "提交中…" : "提交申请"}
|
||||
</button>
|
||||
|
||||
<p className="mt-4 whitespace-pre-line text-center text-sm leading-relaxed text-amber-500">
|
||||
{"🔍 提交后将进行审核\n💰 需支付基本场地/管理费"}
|
||||
</p>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user