报名表单
All checks were successful
Deploy to Server / deploy (push) Successful in 37s

This commit is contained in:
jeremygan2021
2026-02-23 15:39:47 +08:00
parent c3fab398bb
commit 0bf5f94483
5 changed files with 52 additions and 29 deletions

View File

@@ -1,8 +1,7 @@
import React, { useState, useEffect } from 'react';
import { Form, Input, Button, Card, List, Tag, Typography, message, Space, Statistic, Divider, Modal, Descriptions, Tabs } from 'antd';
import { MobileOutlined, LockOutlined, SearchOutlined, CarOutlined, InboxOutlined, SafetyCertificateOutlined, CheckCircleOutlined, ClockCircleOutlined, CloseCircleOutlined, UserOutlined, EnvironmentOutlined, PhoneOutlined, CalendarOutlined } from '@ant-design/icons';
import { queryMyOrders, getMySignups } from '../api';
import { motion } from 'framer-motion';
import api, { getMySignups } from '../api';
import LoginModal from '../components/LoginModal';
import { useAuth } from '../context/AuthContext';
import { useNavigate } from 'react-router-dom';
@@ -41,8 +40,6 @@ const MyOrders = () => {
const handleQueryData = async () => {
setLoading(true);
try {
const { default: api } = await import('../api');
// Parallel fetch
const [ordersRes, activitiesRes] = await Promise.allSettled([
api.get('/orders/'),
@@ -344,7 +341,7 @@ const MyOrders = () => {
onLoginSuccess={(userData) => {
login(userData);
if (userData.phone_number) {
handleQueryOrders(userData.phone_number);
handleQueryData();
}
}}
/>

View File

@@ -28,6 +28,7 @@ const ActivityDetail = () => {
const [signupFormVisible, setSignupFormVisible] = useState(false);
const [paymentModalVisible, setPaymentModalVisible] = useState(false);
const [paymentInfo, setPaymentInfo] = useState(null);
const [isPaidSuccess, setIsPaidSuccess] = useState(false);
const [form] = Form.useForm();
// Header animation: transparent to white with shadow
@@ -96,6 +97,7 @@ const ActivityDetail = () => {
// 检查是否需要支付
if (data.payment_required) {
setPaymentInfo(data);
setIsPaidSuccess(false);
// 先关闭报名表单,确保层级正确
setSignupFormVisible(false);
// 延迟一点点时间打开支付弹窗,避免状态更新冲突
@@ -125,14 +127,13 @@ const ActivityDetail = () => {
// Polling for payment status
useEffect(() => {
let timer;
if (paymentModalVisible && paymentInfo?.order_id) {
if (paymentModalVisible && paymentInfo?.order_id && !isPaidSuccess) {
timer = setInterval(async () => {
try {
const response = await queryOrderStatus(paymentInfo.order_id);
if (response.data.status === 'paid') {
setIsPaidSuccess(true);
message.success('支付成功,报名已确认!');
setPaymentModalVisible(false);
setPaymentInfo(null);
// Trigger success effects
confetti({
@@ -152,7 +153,7 @@ const ActivityDetail = () => {
}, 3000);
}
return () => clearInterval(timer);
}, [paymentModalVisible, paymentInfo, id, queryClient]);
}, [paymentModalVisible, paymentInfo, id, queryClient, isPaidSuccess]);
const handleShare = async () => {
const url = window.location.href;
@@ -475,10 +476,27 @@ const ActivityDetail = () => {
</Form>
</Modal>
<Modal
title="微信支付"
title={isPaidSuccess ? "支付成功" : "微信支付"}
open={paymentModalVisible}
onCancel={() => setPaymentModalVisible(false)}
footer={null}
onCancel={() => {
setPaymentModalVisible(false);
if (isPaidSuccess) {
setPaymentInfo(null);
}
}}
footer={[
<Button
key="ok"
type="primary"
disabled={!isPaidSuccess}
onClick={() => {
setPaymentModalVisible(false);
setPaymentInfo(null);
}}
>
{isPaidSuccess ? '完成' : '等待支付...'}
</Button>
]}
destroyOnHidden
width={360}
zIndex={1001} // 确保层级高于其他弹窗
@@ -486,20 +504,26 @@ const ActivityDetail = () => {
<div style={{ textAlign: 'center', padding: '20px 0' }}>
{paymentInfo?.code_url ? (
<>
<div style={{ background: '#fff', padding: 10, display: 'inline-block' }}>
<QRCodeSVG value={paymentInfo.code_url} size={200} />
</div>
<p style={{ marginTop: 20, fontSize: 18, fontWeight: 'bold' }}>¥{paymentInfo.price}</p>
<p style={{ color: '#666' }}>请使用微信扫一扫支付</p>
{!isPaidSuccess ? (
<>
<div style={{ background: '#fff', padding: 10, display: 'inline-block' }}>
<QRCodeSVG value={paymentInfo.code_url} size={200} />
</div>
<p style={{ marginTop: 20, fontSize: 18, fontWeight: 'bold' }}>¥{paymentInfo.price}</p>
<p style={{ color: '#666' }}>请使用微信扫一扫支付</p>
</>
) : (
<div style={{ padding: '20px 0' }}>
<div style={{ fontSize: 48, color: '#52c41a', marginBottom: 16 }}>
<i className="anticon anticon-check-circle"><svg viewBox="64 64 896 896" focusable="false" data-icon="check-circle" width="1em" height="1em" fill="currentColor" aria-hidden="true"><path d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm193.5 301.7l-210.6 292a31.8 31.8 0 01-51.7 0L318.5 484.9c-3.8-5.3 0-12.7 6.5-12.7h46.9c10.2 0 19.9 4.9 25.9 13.3l71.2 98.8 157.2-218c6-8.3 15.6-13.3 25.9-13.3H699c6.5 0 10.3 7.4 6.5 12.7z"></path></svg></i>
</div>
<p style={{ fontSize: 16, fontWeight: 'bold' }}>支付成功</p>
</div>
)}
</>
) : (
<Spin tip="正在生成二维码..." />
)}
<div style={{ marginTop: 20 }}>
<Button type="primary" onClick={() => window.location.reload()}>
我已支付
</Button>
</div>
</div>
</Modal>