报名表单
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 { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
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 { 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 styles from '../../components/activity/activity.module.less';
import { pageTransition, buttonTap } from '../../animation';
@@ -119,9 +119,19 @@ const ActivityDetail = () => {
};
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);
};
const normFile = (e) => {
if (Array.isArray(e)) {
return e;
}
return e?.fileList;
};
if (isLoading) {
return (
<div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', height: '100vh', background: '#1f1f1f' }}>
@@ -315,16 +325,78 @@ const ActivityDetail = () => {
destroyOnHidden
>
<Form form={form} onFinish={handleFormSubmit} layout="vertical">
{activity.signup_form_config && activity.signup_form_config.map(field => (
<Form.Item
key={field.name}
name={field.name}
label={field.label}
rules={[{ required: field.required, message: `请填写${field.label}` }]}
>
<Input placeholder={`请输入${field.label}`} />
</Form.Item>
{activity.signup_form_config && activity.signup_form_config.map(field => {
let inputNode;
const commonProps = {
placeholder: field.placeholder || `请输入${field.label}`,
};
switch (field.type) {
case 'select':
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>
</Modal>
</motion.div>