b06cf69942
- 商城页改为Tab切换(储值卡/会员卡)+卡片列表,新增商品详情页 - 约课页合并会员卡/团课/门票三Tab,日期横滑选择器 - 会员卡预约新增详情页+二次确认弹窗 - 课程列表已预约状态改为后端返回booked/booking_id/booking_type - 前端移除冗余的loadBookings调用,直接读session.booked字段 - 导航栏仅首页custom,其余页面恢复原生导航栏 - membership API支持date参数筛选
242 lines
5.5 KiB
Vue
242 lines
5.5 KiB
Vue
<template>
|
|
<view class="home-container">
|
|
<StatePanel
|
|
v-if="pageState === 'error'"
|
|
title="首页内容加载失败"
|
|
:description="pageMessage"
|
|
primary-text="重试"
|
|
type="error"
|
|
@primary="loadHome"
|
|
/>
|
|
|
|
<block v-else>
|
|
<!-- 全屏轮播 -->
|
|
<view class="banner-wrapper">
|
|
<swiper
|
|
class="banner-swiper"
|
|
circular
|
|
autoplay
|
|
interval="4000"
|
|
duration="600"
|
|
indicator-dots
|
|
indicator-color="rgba(255, 255, 255, 0.4)"
|
|
indicator-active-color="#FFFFFF"
|
|
>
|
|
<swiper-item v-for="(banner, index) in banners" :key="index" @tap="onTapBanner(banner)">
|
|
<view class="banner-item">
|
|
<image :src="banner.image" mode="aspectFill" class="banner-img" />
|
|
</view>
|
|
</swiper-item>
|
|
</swiper>
|
|
</view>
|
|
|
|
<!-- 内容区域 -->
|
|
<view class="content-wrapper">
|
|
<!-- 活动资讯版块 -->
|
|
<view class="section-container">
|
|
<view class="section-header">
|
|
<text class="section-title">公告活动</text>
|
|
</view>
|
|
|
|
<view class="activity-grid">
|
|
<view
|
|
v-for="activity in activities"
|
|
:key="activity.id"
|
|
class="activity-card"
|
|
@tap="navigateToDetail('/pages/ice/activities/detail?id=' + activity.id)"
|
|
>
|
|
<image :src="activity.cover" mode="aspectFill" class="activity-cover" />
|
|
<view class="activity-info">
|
|
<text class="activity-title">{{ activity.title }}</text>
|
|
<text class="activity-date">{{ formatDate(activity.created_at) }}</text>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<VenueSwitchHeader venue-name="冰场馆" />
|
|
</view>
|
|
</block>
|
|
</view>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { ref, onMounted } from 'vue'
|
|
import { homeApi } from '@/modules/ice/api/home'
|
|
import { errorMessage } from '@/modules/ice/api/session'
|
|
import VenueSwitchHeader from '@/components/VenueSwitchHeader.vue'
|
|
import StatePanel from '@/components/ice/StatePanel.vue'
|
|
|
|
const todayStr = ref('')
|
|
const banners = ref([])
|
|
const activities = ref([])
|
|
const pageState = ref('ready')
|
|
const pageMessage = ref('')
|
|
|
|
onMounted(() => {
|
|
const days = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六']
|
|
const now = new Date()
|
|
todayStr.value = `${now.getMonth() + 1}月${now.getDate()}日 ${days[now.getDay()]}`
|
|
loadHome()
|
|
})
|
|
|
|
const loadHome = async () => {
|
|
try {
|
|
const data = await homeApi.getHome({
|
|
bannerLimit: 5
|
|
})
|
|
banners.value = data.banners
|
|
activities.value = data.activities
|
|
pageState.value = 'ready'
|
|
pageMessage.value = ''
|
|
} catch (err) {
|
|
pageState.value = 'error'
|
|
pageMessage.value = errorMessage(err, '首页内容加载失败,请稍后重试。')
|
|
}
|
|
}
|
|
|
|
const navigateToDetail = (url) => {
|
|
uni.navigateTo({ url })
|
|
}
|
|
|
|
const onTapBanner = (banner) => {
|
|
if (banner.link_type === 'course' && banner.link_value) {
|
|
navigateToDetail(`/pages/ice/courses/detail?id=${banner.link_value}`)
|
|
} else if (banner.link_type === 'activity' && banner.link_value) {
|
|
navigateToDetail(`/pages/ice/activities/detail?id=${banner.link_value}`)
|
|
}
|
|
}
|
|
|
|
const formatDate = (dateStr) => {
|
|
const date = new Date(dateStr)
|
|
return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')}`
|
|
}
|
|
|
|
defineExpose({ refresh: loadHome })
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
.home-container {
|
|
background-color: $bg-color-soft;
|
|
min-height: 100vh;
|
|
}
|
|
|
|
/* 全屏轮播 */
|
|
.banner-wrapper {
|
|
width: 100%;
|
|
|
|
.banner-swiper {
|
|
width: 100%;
|
|
height: 33.33vh;
|
|
}
|
|
|
|
.banner-item {
|
|
position: relative;
|
|
width: 100%;
|
|
height: 100%;
|
|
}
|
|
|
|
.banner-img {
|
|
width: 100%;
|
|
height: 100%;
|
|
background-color: $bg-color-hover;
|
|
}
|
|
}
|
|
|
|
/* 内容区域 */
|
|
.content-wrapper {
|
|
padding: $spacing-lg $spacing-md;
|
|
}
|
|
|
|
/* 板块通用头部 */
|
|
.section-container {
|
|
margin-bottom: $spacing-lg;
|
|
}
|
|
|
|
.section-header {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
margin-bottom: $spacing-md;
|
|
padding: 0 4rpx;
|
|
|
|
.section-title {
|
|
font-size: 28rpx;
|
|
font-weight: 700;
|
|
letter-spacing: 0.5rpx;
|
|
color: $text-color-main;
|
|
position: relative;
|
|
padding-left: $spacing-sm;
|
|
|
|
&::before {
|
|
content: '';
|
|
position: absolute;
|
|
left: 0;
|
|
top: 10%;
|
|
bottom: 10%;
|
|
width: 4rpx;
|
|
background-color: $text-color-main;
|
|
}
|
|
}
|
|
|
|
.section-more {
|
|
font-size: 24rpx;
|
|
color: $text-color-muted;
|
|
}
|
|
}
|
|
|
|
/* 极简活动卡片 */
|
|
.activity-grid {
|
|
display: grid;
|
|
grid-template-columns: 1fr 1;
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: $spacing-sm;
|
|
}
|
|
|
|
.activity-card {
|
|
display: flex;
|
|
background-color: $bg-color-main;
|
|
border-radius: $border-radius-base;
|
|
border: 1rpx solid $bg-color-hover;
|
|
overflow: hidden;
|
|
|
|
.activity-cover {
|
|
width: 180rpx;
|
|
height: 130rpx;
|
|
background-color: $bg-color-hover;
|
|
}
|
|
|
|
.activity-info {
|
|
flex: 1;
|
|
padding: $spacing-sm $spacing-md;
|
|
display: flex;
|
|
flex-direction: column;
|
|
justify-content: space-between;
|
|
}
|
|
|
|
.activity-title {
|
|
font-size: 26rpx;
|
|
font-weight: 600;
|
|
color: $text-color-main;
|
|
line-height: 1.3;
|
|
display: -webkit-box;
|
|
-webkit-box-orient: vertical;
|
|
-webkit-line-clamp: 2;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.activity-date {
|
|
font-size: 20rpx;
|
|
color: $text-color-light;
|
|
}
|
|
}
|
|
|
|
.empty-placeholder {
|
|
text-align: center;
|
|
padding: $spacing-xl 0;
|
|
color: $text-color-light;
|
|
font-size: 24rpx;
|
|
}
|
|
</style>
|