This commit is contained in:
169
frontend/src/components/competition/ProjectSubmission.jsx
Normal file
169
frontend/src/components/competition/ProjectSubmission.jsx
Normal file
@@ -0,0 +1,169 @@
|
||||
import React, { useState } from 'react';
|
||||
import { Card, Button, Form, Input, Upload, message, Modal, Select } from 'antd';
|
||||
import { UploadOutlined, CloudUploadOutlined, LinkOutlined } from '@ant-design/icons';
|
||||
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
||||
import { createProject, updateProject, submitProject, uploadProjectFile } from '../../api';
|
||||
|
||||
const { TextArea } = Input;
|
||||
const { Option } = Select;
|
||||
|
||||
const ProjectSubmission = ({ competitionId, initialValues, onCancel, onSuccess }) => {
|
||||
const [form] = Form.useForm();
|
||||
const [fileList, setFileList] = useState([]);
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
const createMutation = useMutation({
|
||||
mutationFn: createProject,
|
||||
onSuccess: () => {
|
||||
message.success('项目创建成功');
|
||||
queryClient.invalidateQueries(['projects']);
|
||||
onSuccess();
|
||||
},
|
||||
onError: (error) => {
|
||||
message.error(`创建失败: ${error.message}`);
|
||||
}
|
||||
});
|
||||
|
||||
const updateMutation = useMutation({
|
||||
mutationFn: (data) => updateProject(initialValues.id, data),
|
||||
onSuccess: () => {
|
||||
message.success('项目更新成功');
|
||||
queryClient.invalidateQueries(['projects']);
|
||||
onSuccess();
|
||||
},
|
||||
onError: (error) => {
|
||||
message.error(`更新失败: ${error.message}`);
|
||||
}
|
||||
});
|
||||
|
||||
const uploadMutation = useMutation({
|
||||
mutationFn: uploadProjectFile,
|
||||
onSuccess: (data) => {
|
||||
message.success('文件上传成功');
|
||||
setFileList([...fileList, data]); // Add file to list (assuming response format)
|
||||
},
|
||||
onError: (error) => {
|
||||
message.error(`上传失败: ${error.message}`);
|
||||
}
|
||||
});
|
||||
|
||||
const onFinish = (values) => {
|
||||
const data = {
|
||||
...values,
|
||||
competition: competitionId,
|
||||
// Handle file URLs/IDs if needed in create/update
|
||||
};
|
||||
|
||||
if (initialValues?.id) {
|
||||
updateMutation.mutate(data);
|
||||
} else {
|
||||
createMutation.mutate(data);
|
||||
}
|
||||
};
|
||||
|
||||
const handleUpload = ({ file, onSuccess, onError }) => {
|
||||
const formData = new FormData();
|
||||
formData.append('file', file);
|
||||
formData.append('project', initialValues?.id || ''); // Need project ID first usually
|
||||
|
||||
// Upload logic might need adjustment: create project first, then upload files?
|
||||
// Or upload to temp storage then link?
|
||||
// For simplicity, let's assume we create project first if not exists
|
||||
if (!initialValues?.id) {
|
||||
message.warning('请先保存项目基本信息再上传文件');
|
||||
return;
|
||||
}
|
||||
|
||||
uploadMutation.mutate(formData);
|
||||
};
|
||||
|
||||
return (
|
||||
<Modal
|
||||
title={initialValues ? "编辑项目" : "提交新项目"}
|
||||
open={true}
|
||||
onCancel={onCancel}
|
||||
footer={null}
|
||||
width={800}
|
||||
>
|
||||
<Form
|
||||
form={form}
|
||||
layout="vertical"
|
||||
onFinish={onFinish}
|
||||
initialValues={initialValues}
|
||||
>
|
||||
<Form.Item
|
||||
name="title"
|
||||
label="项目名称"
|
||||
rules={[{ required: true, message: '请输入项目名称' }]}
|
||||
>
|
||||
<Input placeholder="请输入项目名称" />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name="description"
|
||||
label="项目简介"
|
||||
rules={[{ required: true, message: '请输入项目简介' }]}
|
||||
>
|
||||
<TextArea rows={4} placeholder="简要描述您的项目创意和功能" />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name="team_info"
|
||||
label="团队介绍"
|
||||
>
|
||||
<TextArea rows={3} placeholder="介绍您的团队成员和分工" />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name="cover_image_url"
|
||||
label="封面图片链接"
|
||||
rules={[{ type: 'url', message: '请输入有效的URL' }]}
|
||||
>
|
||||
<Input prefix={<LinkOutlined />} placeholder="https://example.com/image.jpg" />
|
||||
</Form.Item>
|
||||
|
||||
{/* File Upload Section - Only visible if project exists */}
|
||||
{initialValues?.id && (
|
||||
<Form.Item label="项目附件 (PPT/PDF/视频)">
|
||||
<Upload
|
||||
customRequest={handleUpload}
|
||||
listType="picture"
|
||||
maxCount={5}
|
||||
>
|
||||
<Button icon={<CloudUploadOutlined />}>上传文件 (最大50MB)</Button>
|
||||
</Upload>
|
||||
</Form.Item>
|
||||
)}
|
||||
|
||||
<Form.Item>
|
||||
<div style={{ display: 'flex', justifyContent: 'flex-end', gap: 10 }}>
|
||||
<Button onClick={onCancel}>取消</Button>
|
||||
<Button type="primary" htmlType="submit" loading={createMutation.isLoading || updateMutation.isLoading}>
|
||||
保存草稿
|
||||
</Button>
|
||||
{initialValues?.id && (
|
||||
<Button
|
||||
type="primary"
|
||||
danger
|
||||
onClick={() => {
|
||||
Modal.confirm({
|
||||
title: '确认提交?',
|
||||
content: '提交后将无法修改,确认提交吗?',
|
||||
onOk: () => submitProject(initialValues.id).then(() => {
|
||||
message.success('提交成功');
|
||||
onSuccess();
|
||||
})
|
||||
})
|
||||
}}
|
||||
>
|
||||
正式提交
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
||||
export default ProjectSubmission;
|
||||
Reference in New Issue
Block a user