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

This commit is contained in:
jeremygan2021
2026-03-10 12:35:41 +08:00
parent 417cda952d
commit 3ada996915
9 changed files with 388 additions and 11 deletions

View File

@@ -0,0 +1,111 @@
import { View, Text, Button, Image, ScrollView, RichText } from '@tarojs/components'
import Taro, { useLoad } from '@tarojs/taro'
import { useState } from 'react'
import { getCompetitionDetail, enrollCompetition, getMyCompetitionEnrollment } from '../../api'
import './detail.scss'
export default function CompetitionDetail() {
const [detail, setDetail] = useState<any>(null)
const [enrollment, setEnrollment] = useState<any>(null)
const [loading, setLoading] = useState(false)
useLoad((options) => {
const { id } = options
if (id) {
fetchDetail(id)
fetchEnrollment(id)
}
})
const fetchDetail = async (id) => {
setLoading(true)
try {
const res = await getCompetitionDetail(id)
setDetail(res)
} catch (e) {
Taro.showToast({ title: '加载详情失败', icon: 'none' })
} finally {
setLoading(false)
}
}
const fetchEnrollment = async (id) => {
try {
const res = await getMyCompetitionEnrollment(id)
setEnrollment(res)
} catch (e) {
// 没报名则无数据,忽略
}
}
const handleEnroll = async () => {
if (!detail) return
try {
await enrollCompetition(detail.id, { role: 'contestant' })
Taro.showToast({ title: '报名成功', icon: 'success' })
fetchEnrollment(detail.id)
} catch (e) {
Taro.showToast({ title: e.message || '报名失败', icon: 'none' })
}
}
const getStatusText = (status) => {
const map = {
'registration': '报名中',
'submission': '作品提交中',
'judging': '评审中',
'ended': '已结束',
}
return map[status] || status
}
if (loading || !detail) return <View className='loading'>...</View>
return (
<ScrollView scrollY className='comp-detail'>
<Image
className='banner'
mode='aspectFill'
src={detail.display_cover_image || 'https://via.placeholder.com/400x200'}
/>
<View className='content'>
<View className='header'>
<Text className='title'>{detail.title}</Text>
<Text className={`status ${detail.status}`}>{getStatusText(detail.status)}</Text>
</View>
<View className='section'>
<Text className='section-title'></Text>
<RichText nodes={detail.description} />
</View>
<View className='section'>
<Text className='section-title'></Text>
<RichText nodes={detail.rule_description} />
</View>
<View className='section'>
<Text className='section-title'></Text>
<RichText nodes={detail.condition_description} />
</View>
</View>
<View className='footer-action'>
{enrollment ? (
<Button disabled className='btn enrolled'>
{enrollment.status === 'approved' ? '已报名' : '审核中'}
</Button>
) : (
<Button
className='btn enroll'
onClick={handleEnroll}
disabled={detail.status !== 'registration'}
>
{detail.status === 'registration' ? '立即报名' : '报名未开始/已结束'}
</Button>
)}
</View>
</ScrollView>
)
}