This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import React, { useState } from 'react';
|
||||
import { useParams, useNavigate } from 'react-router-dom';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { useQuery, useQueryClient } from '@tanstack/react-query';
|
||||
import { Typography, Tabs, Button, Row, Col, Card, Statistic, Tag, Descriptions, Empty, message, Spin } from 'antd';
|
||||
import { CalendarOutlined, TrophyOutlined, UserOutlined, FileTextOutlined, CloudUploadOutlined, CopyOutlined, CheckOutlined } from '@ant-design/icons';
|
||||
import ReactMarkdown from 'react-markdown';
|
||||
@@ -79,6 +79,7 @@ const CodeBlock = ({ inline, className, children, ...props }) => {
|
||||
const CompetitionDetail = () => {
|
||||
const { id } = useParams();
|
||||
const navigate = useNavigate();
|
||||
const queryClient = useQueryClient();
|
||||
const { user, showLoginModal } = useAuth();
|
||||
const [activeTab, setActiveTab] = useState('details');
|
||||
const [submissionModalVisible, setSubmissionModalVisible] = useState(false);
|
||||
@@ -104,6 +105,15 @@ const CompetitionDetail = () => {
|
||||
retry: false
|
||||
});
|
||||
|
||||
// Fetch my project if enrolled
|
||||
const { data: myProjects, isLoading: loadingMyProject } = useQuery({
|
||||
queryKey: ['myProject', id, enrollment?.id],
|
||||
queryFn: () => getProjects({ competition: id, contestant: enrollment.id }).then(res => res.data),
|
||||
enabled: !!enrollment?.id
|
||||
});
|
||||
|
||||
const myProject = myProjects?.results?.[0];
|
||||
|
||||
const handleEnroll = async () => {
|
||||
if (!user) {
|
||||
showLoginModal();
|
||||
@@ -297,8 +307,15 @@ const CompetitionDetail = () => {
|
||||
</Button>
|
||||
)}
|
||||
{isContestant && (
|
||||
<Button icon={<CloudUploadOutlined />} onClick={() => setSubmissionModalVisible(true)}>
|
||||
提交/管理作品
|
||||
<Button
|
||||
icon={<CloudUploadOutlined />}
|
||||
loading={loadingMyProject}
|
||||
onClick={() => {
|
||||
setEditingProject(myProject || null);
|
||||
setSubmissionModalVisible(true);
|
||||
}}
|
||||
>
|
||||
{myProject ? '管理/修改作品' : '提交作品'}
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
@@ -325,6 +342,8 @@ const CompetitionDetail = () => {
|
||||
setSubmissionModalVisible(false);
|
||||
setEditingProject(null);
|
||||
// Refetch projects
|
||||
queryClient.invalidateQueries(['projects']);
|
||||
queryClient.invalidateQueries(['myProject']);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
||||
@@ -12,6 +12,15 @@ const ProjectSubmission = ({ competitionId, initialValues, onCancel, onSuccess }
|
||||
const [fileList, setFileList] = useState([]);
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
// Reset form when initialValues changes (important for switching between create/edit)
|
||||
React.useEffect(() => {
|
||||
if (initialValues) {
|
||||
form.setFieldsValue(initialValues);
|
||||
} else {
|
||||
form.resetFields();
|
||||
}
|
||||
}, [initialValues, form]);
|
||||
|
||||
const createMutation = useMutation({
|
||||
mutationFn: createProject,
|
||||
onSuccess: () => {
|
||||
@@ -62,6 +71,13 @@ const ProjectSubmission = ({ competitionId, initialValues, onCancel, onSuccess }
|
||||
};
|
||||
|
||||
const handleUpload = ({ file, onSuccess, onError }) => {
|
||||
if (!initialValues?.id) {
|
||||
message.warning('请先保存项目基本信息再上传文件');
|
||||
// Prevent default upload
|
||||
onError(new Error('请先保存项目'));
|
||||
return;
|
||||
}
|
||||
|
||||
const formData = new FormData();
|
||||
formData.append('file', file);
|
||||
formData.append('project', initialValues?.id || ''); // Need project ID first usually
|
||||
@@ -70,7 +86,7 @@ const ProjectSubmission = ({ competitionId, initialValues, onCancel, onSuccess }
|
||||
// Or upload to temp storage then link?
|
||||
// For simplicity, let's assume we create project first if not exists
|
||||
if (!initialValues?.id) {
|
||||
message.warning('请先保存项目基本信息再上传文件');
|
||||
// Already handled above
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -79,7 +95,7 @@ const ProjectSubmission = ({ competitionId, initialValues, onCancel, onSuccess }
|
||||
|
||||
return (
|
||||
<Modal
|
||||
title={initialValues ? "编辑项目" : "提交新项目"}
|
||||
title={initialValues?.id ? "修改已提交项目" : "提交新项目"}
|
||||
open={true}
|
||||
onCancel={onCancel}
|
||||
footer={null}
|
||||
@@ -114,6 +130,12 @@ const ProjectSubmission = ({ competitionId, initialValues, onCancel, onSuccess }
|
||||
<TextArea rows={3} placeholder="介绍您的团队成员和分工" />
|
||||
</Form.Item>
|
||||
|
||||
{initialValues?.status === 'submitted' && (
|
||||
<div style={{ marginBottom: 24, color: '#faad14' }}>
|
||||
注意:您已正式提交该项目,修改后需要重新审核(如适用)。
|
||||
</div>
|
||||
)}
|
||||
|
||||
<Form.Item
|
||||
name="cover_image_url"
|
||||
label="封面图片链接"
|
||||
@@ -139,7 +161,7 @@ const ProjectSubmission = ({ competitionId, initialValues, onCancel, onSuccess }
|
||||
<div style={{ display: 'flex', justifyContent: 'flex-end', gap: 10 }}>
|
||||
<Button onClick={onCancel}>取消</Button>
|
||||
<Button type="primary" htmlType="submit" loading={createMutation.isLoading || updateMutation.isLoading}>
|
||||
保存草稿
|
||||
{initialValues?.id ? '保存修改' : '保存草稿'}
|
||||
</Button>
|
||||
{initialValues?.id && (
|
||||
<Button
|
||||
|
||||
Reference in New Issue
Block a user