比赛
All checks were successful
Deploy to Server / deploy (push) Successful in 37s

This commit is contained in:
jeremygan2021
2026-03-10 13:47:28 +08:00
parent af763b1bee
commit 3d74ccc04f
9 changed files with 470 additions and 27 deletions

View File

@@ -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']);
}}
/>
)}

View File

@@ -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