This commit is contained in:
111
miniprogram/src/pages/competition/detail.tsx
Normal file
111
miniprogram/src/pages/competition/detail.tsx
Normal 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>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user