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

This commit is contained in:
jeremygan2021
2026-03-10 13:32:04 +08:00
parent 3ada996915
commit af763b1bee
7 changed files with 447 additions and 31 deletions

View File

@@ -12,6 +12,16 @@ import dayjs from 'dayjs';
import { getCompetitionDetail, getProjects, getMyCompetitionEnrollment, enrollCompetition } from '../../api';
import ProjectSubmission from './ProjectSubmission';
import { useAuth } from '../../context/AuthContext';
import 'github-markdown-css/github-markdown-dark.css';
const getImageUrl = (url) => {
if (!url) return '';
if (url.startsWith('http') || url.startsWith('//')) return url;
const apiUrl = import.meta.env.VITE_API_URL || 'http://localhost:8000/api';
// Remove /api suffix if present to get the root URL for media files
const baseUrl = apiUrl.replace(/\/api\/?$/, '');
return `${baseUrl}${url}`;
};
const { Title, Paragraph } = Typography;
@@ -77,19 +87,19 @@ const CompetitionDetail = () => {
// Fetch competition details
const { data: competition, isLoading: loadingDetail } = useQuery({
queryKey: ['competition', id],
queryFn: () => getCompetitionDetail(id)
queryFn: () => getCompetitionDetail(id).then(res => res.data)
});
// Fetch projects (for leaderboard/display)
const { data: projects } = useQuery({
queryKey: ['projects', id],
queryFn: () => getProjects({ competition: id, status: 'submitted' })
queryFn: () => getProjects({ competition: id, status: 'submitted' }).then(res => res.data)
});
// Check enrollment status
const { data: enrollment, refetch: refetchEnrollment } = useQuery({
queryKey: ['enrollment', id],
queryFn: () => getMyCompetitionEnrollment(id),
queryFn: () => getMyCompetitionEnrollment(id).then(res => res.data),
enabled: !!user,
retry: false
});
@@ -140,7 +150,7 @@ const CompetitionDetail = () => {
rehypePlugins={[rehypeRaw]}
components={{
code: CodeBlock,
img: (props) => <img {...props} style={{ maxWidth: '100%', borderRadius: '8px' }} />,
img: (props) => <img {...props} src={getImageUrl(props.src)} style={{ maxWidth: '100%', borderRadius: '8px' }} />,
h1: (props) => <h1 {...props} style={{ color: '#fff', borderBottom: '1px solid #333', paddingBottom: '0.3em' }} />,
h2: (props) => <h2 {...props} style={{ color: '#fff', borderBottom: '1px solid #333', paddingBottom: '0.3em' }} />,
h3: (props) => <h3 {...props} style={{ color: '#eee' }} />,
@@ -162,7 +172,7 @@ const CompetitionDetail = () => {
rehypePlugins={[rehypeRaw]}
components={{
code: CodeBlock,
img: (props) => <img {...props} style={{ maxWidth: '100%', borderRadius: '8px' }} />,
img: (props) => <img {...props} src={getImageUrl(props.src)} style={{ maxWidth: '100%', borderRadius: '8px' }} />,
h1: (props) => <h1 {...props} style={{ color: '#fff', borderBottom: '1px solid #333', paddingBottom: '0.3em' }} />,
h2: (props) => <h2 {...props} style={{ color: '#fff', borderBottom: '1px solid #333', paddingBottom: '0.3em' }} />,
h3: (props) => <h3 {...props} style={{ color: '#eee' }} />,
@@ -184,7 +194,7 @@ const CompetitionDetail = () => {
rehypePlugins={[rehypeRaw]}
components={{
code: CodeBlock,
img: (props) => <img {...props} style={{ maxWidth: '100%', borderRadius: '8px' }} />,
img: (props) => <img {...props} src={getImageUrl(props.src)} style={{ maxWidth: '100%', borderRadius: '8px' }} />,
h1: (props) => <h1 {...props} style={{ color: '#fff', borderBottom: '1px solid #333', paddingBottom: '0.3em' }} />,
h2: (props) => <h2 {...props} style={{ color: '#fff', borderBottom: '1px solid #333', paddingBottom: '0.3em' }} />,
h3: (props) => <h3 {...props} style={{ color: '#eee' }} />,
@@ -210,14 +220,18 @@ const CompetitionDetail = () => {
<Col key={project.id} xs={24} sm={12} md={8}>
<Card
hoverable
cover={<img alt={project.title} src={project.display_cover_image || 'placeholder.jpg'} style={{ height: 180, objectFit: 'cover' }} />}
cover={<img alt={project.title} src={getImageUrl(project.display_cover_image) || 'placeholder.jpg'} style={{ height: 180, objectFit: 'cover' }} />}
actions={[
<Button type="link" onClick={() => navigate(`/projects/${project.id}`)}>查看详情</Button>
]}
>
<Card.Meta
title={project.title}
description={`得分: ${project.final_score || '待定'}`}
description={
enrollment && project.contestant === enrollment.id
? `得分: ${project.final_score || '待定'}`
: null
}
avatar={<UserOutlined />}
/>
</Card>
@@ -245,8 +259,8 @@ const CompetitionDetail = () => {
<div style={{ color: '#888', fontSize: 12 }}>{project.contestant_info?.nickname}</div>
</div>
<div style={{ fontSize: 24, color: '#00b96b', fontWeight: 'bold' }}>
{project.final_score}
</div>
{enrollment && project.contestant === enrollment.id ? project.final_score : '**'}
</div>
</div>
))}
</Card>
@@ -258,7 +272,7 @@ const CompetitionDetail = () => {
<div style={{ maxWidth: 1200, margin: '0 auto', padding: '24px' }}>
<div style={{
height: 300,
backgroundImage: `url(${competition.display_cover_image})`,
backgroundImage: `url(${getImageUrl(competition.display_cover_image)})`,
backgroundSize: 'cover',
backgroundPosition: 'center',
borderRadius: 16,