163 lines
4.1 KiB
Vue
163 lines
4.1 KiB
Vue
<template>
|
|
<!-- 推荐课程容器 -->
|
|
<view class="recommend-courses">
|
|
<!-- 区域标题栏 -->
|
|
<view class="section-header">
|
|
<!-- 区域标题 -->
|
|
<text class="section-title">推荐课程</text>
|
|
<!-- 查看更多按钮 -->
|
|
<view class="view-more" @tap="goMore">
|
|
<text>查看更多</text>
|
|
<text class="arrow">
|
|
<uni-icons type="right" size="20" color="#8CA0B0"/>
|
|
</text>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 课程横向滚动容器 -->
|
|
<scroll-view class="courses-scroll" scroll-x="true" :show-scrollbar="false">
|
|
<!-- 课程列表 -->
|
|
<view class="courses-list">
|
|
<!-- 课程卡片 -->
|
|
<CourseCard
|
|
v-for="(course, index) in displayCourses"
|
|
:key="course.id || index"
|
|
:course="course"
|
|
@join="handleJoinCourse"
|
|
/>
|
|
</view>
|
|
</scroll-view>
|
|
</view>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { computed } from 'vue'
|
|
import CourseCard from './CourseCard.vue'
|
|
|
|
// 接收父组件传递的数据
|
|
const props = defineProps({
|
|
data: {
|
|
type: Object,
|
|
default: () => ({ list: [] })
|
|
}
|
|
})
|
|
|
|
// 课程类型映射(用于显示标签)
|
|
const getCourseTypeName = (type) => {
|
|
const typeMap = {
|
|
'1': '瑜伽',
|
|
'2': '搏击',
|
|
'3': '塑形'
|
|
}
|
|
return typeMap[type] || '课程'
|
|
}
|
|
|
|
// 根据课程信息获取标签文本
|
|
const getTag = (course) => {
|
|
if (course.currentMembers >= course.maxMembers) return '已满员'
|
|
if (course.status === '2') return '已结束'
|
|
if (course.currentMembers / course.maxMembers >= 0.8) return '热门'
|
|
return getCourseTypeName(course.courseType)
|
|
}
|
|
|
|
// 根据课程信息获取标签样式类型
|
|
const getTagType = (course) => {
|
|
if (course.currentMembers >= course.maxMembers) return 'full'
|
|
if (course.status === '2') return 'ended'
|
|
if (course.currentMembers / course.maxMembers >= 0.8) return 'hot'
|
|
return 'default'
|
|
}
|
|
|
|
// 计算课程时长
|
|
const calculateDuration = (startTime, endTime) => {
|
|
if (!startTime || !endTime) return '60分钟'
|
|
const start = new Date(startTime)
|
|
const end = new Date(endTime)
|
|
const durationMinutes = Math.floor((end - start) / (1000 * 60))
|
|
return `${durationMinutes}分钟`
|
|
}
|
|
|
|
// 获取课程难度
|
|
const getCourseLevel = (course) => {
|
|
if (course.courseType === '2') return '中级'
|
|
if (course.courseType === '3') return '高级'
|
|
if (course.courseType === '1') return '初级'
|
|
return '初级'
|
|
}
|
|
|
|
// 处理图片URL
|
|
const getImageUrl = (coverImage) => {
|
|
if (!coverImage) return 'https://images.unsplash.com/photo-1534438327276-14e5300c3a48?w=400&q=80'
|
|
if (coverImage.startsWith('http')) return coverImage
|
|
return `https://your-domain.com${coverImage}`
|
|
}
|
|
|
|
// 将原始课程数据转换为卡片需要的格式
|
|
const displayCourses = computed(() => {
|
|
const list = props.data?.list || []
|
|
return list.map(course => ({
|
|
id: course.id,
|
|
image: getImageUrl(course.coverImage),
|
|
tag: getTag(course),
|
|
tagType: getTagType(course),
|
|
name: course.courseName || '未知课程',
|
|
duration: calculateDuration(course.startTime, course.endTime),
|
|
level: getCourseLevel(course),
|
|
participants: course.currentMembers || 0,
|
|
rawData: course
|
|
}))
|
|
})
|
|
|
|
const handleJoinCourse = (course) => {
|
|
if (course.rawData.status === '2') { uni.showToast({ title: '课程已结束', icon: 'none' }); return }
|
|
if (course.rawData.currentMembers >= course.rawData.maxMembers) { uni.showToast({ title: '课程已满员', icon: 'none' }); return }
|
|
uni.navigateTo({ url: `/pages/course/detail?id=${course.id}` })
|
|
}
|
|
|
|
function goMore(){
|
|
uni.navigateTo({ url: '/pages/recommendCourses/index' })
|
|
}
|
|
</script>
|
|
|
|
<style lang="scss">
|
|
.recommend-courses {
|
|
padding: 0 24rpx;
|
|
margin-bottom: 32rpx;
|
|
position: relative;
|
|
z-index: 1;
|
|
}
|
|
|
|
.section-header {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
margin-bottom: 24rpx;
|
|
}
|
|
|
|
.section-title {
|
|
font-size: 34rpx;
|
|
font-weight: 700;
|
|
color: #2D4A5A;
|
|
}
|
|
|
|
.view-more {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 4rpx;
|
|
font-size: 26rpx;
|
|
color: var(--tabbar-text-inactive);
|
|
}
|
|
|
|
.arrow {
|
|
font-size: 32rpx;
|
|
}
|
|
|
|
.courses-scroll {
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.courses-list {
|
|
display: inline-flex;
|
|
gap: 48rpx;
|
|
}
|
|
</style> |