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

This commit is contained in:
jeremygan2021
2026-03-10 11:09:15 +08:00
parent 724dd3857c
commit 417cda952d
11 changed files with 778 additions and 3 deletions

View File

@@ -68,6 +68,33 @@ export const getActivityDetail = (id: number) => request({ url: `/community/acti
export const signupActivity = (id: number, data?: any) => request({ url: `/community/activities/${id}/signup/`, method: 'POST', data })
export const getMySignups = () => request({ url: '/community/activities/my_signups/' })
// Competitions
export const getCompetitions = (params?: any) => request({ url: '/competition/competitions/', data: params })
export const getCompetitionDetail = (id: number) => request({ url: `/competition/competitions/${id}/` })
export const enrollCompetition = (id: number, data: any) => request({ url: `/competition/competitions/${id}/enroll/`, method: 'POST', data })
export const getMyCompetitionEnrollment = (id: number) => request({ url: `/competition/competitions/${id}/my_enrollment/` })
export const getProjects = (params?: any) => request({ url: '/competition/projects/', data: params })
export const getProjectDetail = (id: number) => request({ url: `/competition/projects/${id}/` })
export const createProject = (data: any) => request({ url: '/competition/projects/', method: 'POST', data })
export const updateProject = (id: number, data: any) => request({ url: `/competition/projects/${id}/`, method: 'PATCH', data })
export const submitProject = (id: number) => request({ url: `/competition/projects/${id}/submit/`, method: 'POST' })
export const uploadProjectFile = (filePath: string) => {
const BASE_URL = (typeof process !== 'undefined' && process.env && process.env.TARO_APP_API_URL) || 'https://market.quant-speed.com/api'
return Taro.uploadFile({
url: `${BASE_URL}/competition/files/`,
filePath,
name: 'file',
header: {
'Authorization': `Bearer ${Taro.getStorageSync('token')}`
}
}).then(res => {
if (res.statusCode >= 200 && res.statusCode < 300) {
return JSON.parse(res.data)
}
throw new Error('Upload failed')
})
}
// Upload Media for Forum
export const uploadMedia = (filePath: string, type: 'image' | 'video') => {
const BASE_URL = (typeof process !== 'undefined' && process.env && process.env.TARO_APP_API_URL) || 'https://market.quant-speed.com/api'

View File

@@ -13,7 +13,9 @@ export default defineAppConfig({
'pages/order/payment',
'pages/order/list',
'pages/order/detail',
'pages/user/index'
'pages/user/index',
'pages/competition/index',
'pages/competition/detail'
],
subPackages: [
{

View File

@@ -0,0 +1,74 @@
import { View, Text, Image, ScrollView } from '@tarojs/components'
import Taro, { useLoad } from '@tarojs/taro'
import { useState } from 'react'
import { getCompetitions } from '../../api'
import './index.scss'
export default function CompetitionList() {
const [competitions, setCompetitions] = useState<any[]>([])
const [loading, setLoading] = useState(false)
useLoad(() => {
fetchCompetitions()
})
const fetchCompetitions = async () => {
setLoading(true)
try {
const res = await getCompetitions()
if (res && res.results) {
setCompetitions(res.results)
}
} catch (e) {
Taro.showToast({ title: '加载失败', icon: 'none' })
} finally {
setLoading(false)
}
}
const goDetail = (id) => {
Taro.navigateTo({ url: `/pages/competition/detail?id=${id}` })
}
const getStatusText = (status) => {
const map = {
'registration': '报名中',
'submission': '作品提交中',
'judging': '评审中',
'ended': '已结束',
'draft': '草稿'
}
return map[status] || status
}
return (
<View className='competition-page'>
<ScrollView scrollY className='comp-list'>
{competitions.map(item => (
<View key={item.id} className='comp-card' onClick={() => goDetail(item.id)}>
<Image
className='cover'
mode='aspectFill'
src={item.display_cover_image || 'https://via.placeholder.com/400x200'}
/>
<View className='info'>
<View className='header'>
<Text className='title'>{item.title}</Text>
<Text className={`status ${item.status}`}>{getStatusText(item.status)}</Text>
</View>
<Text className='desc'>{item.description}</Text>
<View className='footer'>
<Text className='time'>
{item.start_time?.split('T')[0]} ~ {item.end_time?.split('T')[0]}
</Text>
</View>
</View>
</View>
))}
{!loading && competitions.length === 0 && (
<View className='empty'></View>
)}
</ScrollView>
</View>
)
}