Files
martial-mini/pages/home/home.vue
2025-12-26 10:20:46 +08:00

344 lines
8.4 KiB
Vue
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<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 || item.totalParticipants || '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>