This commit is contained in:
2025-12-13 09:18:08 +08:00
parent 7807f4b3e4
commit 0042a0220f
79 changed files with 30697 additions and 2 deletions

343
src/pages/home/home.vue Normal file
View File

@@ -0,0 +1,343 @@
<template>
<view class="home-page">
<!-- 轮播图 -->
<view class="banner-section">
<swiper class="banner-swiper" :indicator-dots="true" :autoplay="true" :interval="3000" :duration="500" circular>
<swiper-item v-for="(banner, index) in banners" :key="index">
<image class="banner-image" :src="banner" mode="aspectFill"></image>
</swiper-item>
</swiper>
</view>
<!-- 精品赛事 -->
<view class="section">
<view class="section-header">
<view class="section-title">
<text class="bookmark-icon">📋</text>
<text class="title-text">精品赛事</text>
</view>
<view class="more-btn" @click="goToEventList">
<text>更多</text>
<text class="arrow"></text>
</view>
</view>
<!-- 赛事列表 -->
<view class="event-list">
<view class="event-item" v-for="(item, index) in eventList" :key="index" @click="goToEventDetail(item)">
<view class="event-title">{{ item.title }}</view>
<view class="event-info">
<text class="info-text">地点{{ item.location }}</text>
</view>
<view class="event-info">
<text class="info-text">报名时间{{ item.registerTime }}</text>
</view>
<view class="event-info">
<text class="info-text">比赛时间{{ item.matchTime }}</text>
</view>
<view class="event-info">
<text class="info-text">报名人数{{ item.registerCount }}</text>
</view>
<view class="event-footer">
<button class="register-btn" @click.stop="goToRegister(item)">
{{ item.status === 'finished' ? '报名已结束' : '立即报名' }}
</button>
</view>
<view class="registered-overlay" v-if="item.status === 'finished'">
<text class="status-text">报名已结束</text>
</view>
</view>
</view>
</view>
</view>
</template>
<script>
import competitionAPI from '@/api/competition.js'
export default {
data() {
return {
banners: [],
eventList: []
};
},
onLoad() {
this.loadBanners()
this.loadEvents()
},
methods: {
/**
* 加载轮播图
*/
async loadBanners() {
try {
const res = await competitionAPI.getBannerList({
current: 1,
size: 5
})
// 如果后端返回的是分页数据
if (res.records) {
this.banners = res.records.map(item => item.imageUrl || item.image || item.url)
} else if (Array.isArray(res)) {
this.banners = res.map(item => item.imageUrl || item.image || item.url)
}
// 如果没有数据,使用默认轮播图
if (this.banners.length === 0) {
this.banners = [
'/static/images/bananer1.png',
'/static/images/bananer2.png'
]
}
} catch (err) {
console.error('加载轮播图失败:', err)
// 使用默认轮播图
this.banners = [
'/static/images/bananer1.png',
'/static/images/bananer2.png'
]
}
},
/**
* 加载精品赛事
*/
async loadEvents() {
try {
const res = await competitionAPI.getCompetitionList({
current: 1,
size: 10
})
console.log('赛事列表API返回:', res)
// 如果后端返回的是分页数据
let list = []
if (res.records) {
list = res.records
} else if (Array.isArray(res)) {
list = res
}
// 数据映射:将后端字段转换为前端需要的字段
this.eventList = list.map(item => {
// 尝试多个可能的时间字段
const regStartTime = item.registrationStartTime || item.registerStartTime || item.signUpStartTime
const regEndTime = item.registrationEndTime || item.registerEndTime || item.signUpEndTime
const startTime = item.startTime || item.competitionStartTime || item.beginTime
const endTime = item.endTime || item.competitionEndTime || item.finishTime
return {
id: item.id,
title: item.name || item.title || item.competitionName || '未命名赛事',
location: item.location || item.address || item.venue || '待定',
registerTime: this.formatTimeRange(regStartTime, regEndTime) ||
item.registerTime || item.registrationPeriod || '待定',
matchTime: this.formatTimeRange(startTime, endTime) ||
item.matchTime || item.competitionTime || '待定',
registerCount: item.registrationCount || item.registerCount || item.signUpCount || '0',
status: this.getStatus(item.status)
}
})
console.log('格式化后的赛事列表:', this.eventList)
} catch (err) {
console.error('加载赛事列表失败:', err)
}
},
/**
* 格式化时间范围
* @param {String} startTime 开始时间
* @param {String} endTime 结束时间
* @returns {String}
*/
formatTimeRange(startTime, endTime) {
if (!startTime || !endTime) return ''
const formatDate = (dateStr) => {
if (!dateStr) return ''
const date = new Date(dateStr)
const year = date.getFullYear()
const month = String(date.getMonth() + 1).padStart(2, '0')
const day = String(date.getDate()).padStart(2, '0')
return `${year}.${month}.${day}`
}
return `${formatDate(startTime)}-${formatDate(endTime)}`
},
/**
* 获取赛事状态
* @param {Number|String} status 状态码
* @returns {String}
*/
getStatus(status) {
// 根据后端状态码映射为前端需要的状态
// 1: 报名中, 2: 进行中, 3: 已结束
if (status === 3 || status === '3' || status === 'finished') {
return 'finished'
}
return 'open'
},
goToEventList() {
uni.navigateTo({
url: '/pages/event-list/event-list'
});
},
goToEventDetail(item) {
uni.navigateTo({
url: '/pages/event-detail/event-detail?id=' + item.id
});
},
goToRegister(item) {
if (item.status === 'open') {
uni.navigateTo({
url: '/pages/register-type/register-type?id=' + item.id
});
}
},
goToProfile() {
uni.navigateTo({
url: '/pages/profile/profile'
});
},
goToMyRegistration() {
uni.navigateTo({
url: '/pages/my-registration/my-registration'
});
}
}
};
</script>
<style lang="scss" scoped>
.home-page {
min-height: 100vh;
background-color: #f5f5f5;
padding-bottom: 100rpx;
}
.banner-section {
background: linear-gradient(180deg, #C93639 0%, #f5f5f5 100%);
padding: 30rpx 30rpx 50rpx;
}
.banner-swiper {
width: 100%;
height: 340rpx;
border-radius: 24rpx;
overflow: hidden;
}
.banner-image {
width: 100%;
height: 100%;
}
.section {
padding: 30rpx;
}
.section-header {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 30rpx;
}
.section-title {
display: flex;
align-items: center;
gap: 10rpx;
}
.bookmark-icon {
font-size: 36rpx;
}
.title-text {
font-size: 36rpx;
font-weight: bold;
color: #333333;
}
.more-btn {
display: flex;
align-items: center;
font-size: 28rpx;
color: #666666;
}
.arrow {
font-size: 36rpx;
margin-left: 5rpx;
}
.event-list {
display: flex;
flex-direction: column;
gap: 20rpx;
}
.event-item {
background-color: #fff;
border-radius: 16rpx;
padding: 30rpx;
position: relative;
overflow: hidden;
}
.event-title {
font-size: 32rpx;
font-weight: bold;
color: #333333;
margin-bottom: 20rpx;
line-height: 1.5;
}
.event-info {
margin-bottom: 10rpx;
}
.info-text {
font-size: 26rpx;
color: #666666;
}
.event-footer {
display: flex;
align-items: center;
justify-content: flex-end;
margin-top: 20rpx;
}
.register-btn {
background-color: #C93639;
color: #fff;
padding: 10rpx 30rpx;
border-radius: 50rpx;
font-size: 24rpx;
border: none;
}
.registered-overlay {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(255, 255, 255, 0.9);
display: flex;
align-items: center;
justify-content: center;
}
.status-text {
font-size: 36rpx;
color: #999999;
}
</style>