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

This commit is contained in:
jeremygan2021
2026-02-23 14:56:44 +08:00
parent 84385488ae
commit 6a391c5eab

View File

@@ -3,9 +3,9 @@ import React, { useState, useEffect } from 'react';
import { useParams, useNavigate } from 'react-router-dom'; import { useParams, useNavigate } from 'react-router-dom';
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { motion, useScroll, useTransform } from 'framer-motion'; import { motion, useScroll, useTransform } from 'framer-motion';
import { ArrowLeftOutlined, ShareAltOutlined, CalendarOutlined, ClockCircleOutlined, EnvironmentOutlined, UserOutlined } from '@ant-design/icons'; import { ArrowLeftOutlined, ShareAltOutlined, CalendarOutlined, ClockCircleOutlined, EnvironmentOutlined, UserOutlined, UploadOutlined } from '@ant-design/icons';
import confetti from 'canvas-confetti'; import confetti from 'canvas-confetti';
import { message, Spin, Button, Result, Modal, Form, Input } from 'antd'; import { message, Spin, Button, Result, Modal, Form, Input, Select, Radio, Checkbox, Upload } from 'antd';
import { getActivityDetail, signUpActivity } from '../../api'; import { getActivityDetail, signUpActivity } from '../../api';
import styles from '../../components/activity/activity.module.less'; import styles from '../../components/activity/activity.module.less';
import { pageTransition, buttonTap } from '../../animation'; import { pageTransition, buttonTap } from '../../animation';
@@ -119,9 +119,19 @@ const ActivityDetail = () => {
}; };
const handleFormSubmit = (values) => { const handleFormSubmit = (values) => {
// Handle file uploads if any (convert to base64 or just warn if not supported)
// For now, we just pass values.
// Note: File objects won't serialize to JSON well.
signUpMutation.mutate(values); signUpMutation.mutate(values);
}; };
const normFile = (e) => {
if (Array.isArray(e)) {
return e;
}
return e?.fileList;
};
if (isLoading) { if (isLoading) {
return ( return (
<div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', height: '100vh', background: '#1f1f1f' }}> <div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', height: '100vh', background: '#1f1f1f' }}>
@@ -315,16 +325,78 @@ const ActivityDetail = () => {
destroyOnHidden destroyOnHidden
> >
<Form form={form} onFinish={handleFormSubmit} layout="vertical"> <Form form={form} onFinish={handleFormSubmit} layout="vertical">
{activity.signup_form_config && activity.signup_form_config.map(field => ( {activity.signup_form_config && activity.signup_form_config.map(field => {
<Form.Item let inputNode;
key={field.name} const commonProps = {
name={field.name} placeholder: field.placeholder || `请输入${field.label}`,
label={field.label} };
rules={[{ required: field.required, message: `请填写${field.label}` }]}
> switch (field.type) {
<Input placeholder={`请输入${field.label}`} /> case 'select':
</Form.Item> inputNode = (
))} <Select placeholder={field.placeholder || `请选择${field.label}`}>
{field.options?.map(opt => (
<Select.Option key={opt.value} value={opt.value}>
{opt.label}
</Select.Option>
))}
</Select>
);
break;
case 'radio':
inputNode = (
<Radio.Group>
{field.options?.map(opt => (
<Radio key={opt.value} value={opt.value}>
{opt.label}
</Radio>
))}
</Radio.Group>
);
break;
case 'checkbox':
inputNode = (
<Checkbox.Group>
{field.options?.map(opt => (
<Checkbox key={opt.value} value={opt.value}>
{opt.label}
</Checkbox>
))}
</Checkbox.Group>
);
break;
case 'textarea':
inputNode = <Input.TextArea {...commonProps} rows={4} />;
break;
case 'file':
inputNode = (
<Upload beforeUpload={() => false} maxCount={1}>
<Button icon={<UploadOutlined />}>点击上传</Button>
</Upload>
);
break;
default:
inputNode = <Input {...commonProps} type={field.type === 'tel' ? 'tel' : 'text'} />;
}
const itemProps = {
key: field.name,
name: field.name,
label: field.label,
rules: [{ required: field.required, message: `请填写${field.label}` }],
};
if (field.type === 'file') {
itemProps.valuePropName = 'fileList';
itemProps.getValueFromEvent = normFile;
}
return (
<Form.Item {...itemProps}>
{inputNode}
</Form.Item>
);
})}
</Form> </Form>
</Modal> </Modal>
</motion.div> </motion.div>