2025-08-25 14:17:06 +08:00

556 lines
12 KiB
Vue

<template>
<view class="my-courses-page">
<!-- 自定义导航栏 -->
<view class="navbar" :style="{ paddingTop: statusBarHeight + 'px' }">
<view class="nav-content">
<view class="nav-left" @click="goBack">
<uni-icons type="left" size="24" color="#FF4757"></uni-icons>
</view>
<view class="nav-title">我的课程</view>
<view class="nav-right" @click="goSearch">
<uni-icons type="search" size="24" color="#FF4757"></uni-icons>
</view>
</view>
</view>
<!-- 页面内容 -->
<view class="page-content" :style="{ paddingTop: navBarHeight + 'px' }">
<!-- 标签导航 -->
<view class="tab-nav">
<view class="tab-item" :class="{ active: activeTab === 'learning' }" @click="switchTab('learning')">
<text class="tab-text">学习中</text>
</view>
<view class="tab-divider"></view>
<view class="tab-item" :class="{ active: activeTab === 'completed' }" @click="switchTab('completed')">
<text class="tab-text">已学完</text>
</view>
</view>
<!-- 课程列表 -->
<view class="course-list">
<!-- 有课程数据时显示课程列表 -->
<view v-if="currentCourseList.length > 0">
<view class="course-item" v-for="(course, index) in currentCourseList" :key="course.id" @click="goCourseDetail(course)">
<view class="course-left">
<image :src="course.image" mode="aspectFill" class="course-image"></image>
</view>
<view class="course-right">
<text class="course-title">{{ course.title }}</text>
<view class="course-meta">
<text class="meta-text">{{ course.lessonCount }}</text>
<text class="meta-separator"></text>
<text class="meta-text">{{ course.status }}</text>
<text class="meta-separator"></text>
<text class="meta-text">已学{{ course.learnedCount }}</text>
</view>
<view class="course-tags" v-if="course.tags && course.tags.length > 0">
<view class="tag-item" v-for="tag in course.tags" :key="tag.id">
<text class="tag-text">{{ tag.text }}</text>
</view>
</view>
</view>
</view>
</view>
<!-- 空状态显示 -->
<view v-else class="empty-state">
<view class="empty-icon">
<uni-icons type="book" size="80" color="#E0E0E0"></uni-icons>
</view>
<text class="empty-title">{{ getEmptyTitle() }}</text>
<text class="empty-desc">{{ getEmptyDesc() }}</text>
</view>
</view>
<!-- 订单记录浮动按钮 -->
<view class="floating-order" @click="goOrderRecord">
<view class="order-icon">
<uni-icons type="list" size="24" color="#fff"></uni-icons>
</view>
<text class="order-text">订单记录</text>
</view>
</view>
<!-- 底部导航栏 -->
<view class="bottom-nav">
<view class="nav-item" @click="goPremiumCourses">
<uni-icons type="book" size="24" color="#999"></uni-icons>
<text class="nav-text">精品课</text>
</view>
<view class="nav-item active" @click="goMyCourses">
<view class="nav-icon-active">
<uni-icons type="play" size="24" color="#fff"></uni-icons>
</view>
<text class="nav-text active">我的课程</text>
</view>
</view>
</view>
</template>
<script setup>
import { ref, computed, onMounted } from 'vue'
import course_api from "@/api/course_api.js"
// 响应式数据
const statusBarHeight = ref(0)
const navBarHeight = ref(88)
const activeTab = ref('learning') // 默认激活"学习中"标签
// 课程数据
const courseList = ref({
learning: [
{
id: 1,
title: '找到已购买课程即学习找到已购买课程即可学习',
lessonCount: 26,
status: '更新10节',
learnedCount: 3,
image: '/static/icon_home_my_patient.png',
tags: []
},
{
id: 2,
title: '找到已购买课程即学习找到已购买课程即可学习',
lessonCount: 26,
status: '已完结',
learnedCount: 3,
image: '/static/icon_home_my_library.png',
tags: []
},
{
id: 3,
title: '找到已购买课程即学习找到已购买课程即可学习',
lessonCount: 26,
status: '已完结',
learnedCount: 3,
image: '/static/icon_home_my_patient.png',
tags: [
{ id: 1, text: '福利课堂' }
]
},
{
id: 4,
title: '找到已购买课程即学习找到已购买课程即可学习',
lessonCount: 26,
status: '已完结',
learnedCount: 3,
image: '/static/icon_home_my_patient.png',
tags: [
{ id: 2, text: '学完返现' }
]
}
],
completed: [
{
id: 5,
title: '肝硬化与重症肝病诊疗指南',
lessonCount: 15,
status: '已完结',
learnedCount: 15,
image: '/static/icon_home_my_library.png',
tags: [
{ id: 3, text: '学完返现' }
]
},
{
id: 6,
title: '慢性肝病营养治疗实践',
lessonCount: 12,
status: '已完结',
learnedCount: 12,
image: '/static/icon_home_video.png',
tags: []
}
]
})
// 计算属性
const currentCourseList = computed(() => {
return courseList.value[activeTab.value] || []
})
// 方法
const getSystemInfo = () => {
const systemInfo = uni.getSystemInfoSync()
statusBarHeight.value = systemInfo.statusBarHeight
// #ifdef MP-WEIXIN
navBarHeight.value = systemInfo.statusBarHeight + 44
// #endif
// #ifdef APP-PLUS
navBarHeight.value = systemInfo.statusBarHeight + 44
// #endif
}
const switchTab = (tab) => {
activeTab.value = tab
console.log('切换到标签:', tab)
// 切换标签页后重新获取对应的课程数据
getMyCourses()
}
const goCourseDetail = (course) => {
console.log('进入课程详情:', course.title)
uni.navigateTo({
url: '/pages_course/course_detail/course_detail?id=' + course.id
})
}
const goOrderRecord = () => {
console.log('进入订单记录')
uni.navigateTo({
url: '/pages_course/order_record/order_record'
})
}
const goBack = () => {
uni.navigateBack()
}
const goSearch = () => {
console.log('进入筛选页面')
uni.navigateTo({
url: '/pages_course/course_filter/course_filter'
})
}
const goPremiumCourses = () => {
uni.navigateTo({
url: '/pages_course/course/course'
})
}
const goMyCourses = () => {
// 当前页面,无需跳转
console.log('当前已在我的课程页面')
}
// 获取空状态标题
const getEmptyTitle = () => {
if (activeTab.value === 'learning') {
return '暂无学习中的课程'
} else if (activeTab.value === 'completed') {
return '暂无已完成的课程'
}
return '暂无课程'
}
// 获取空状态描述
const getEmptyDesc = () => {
if (activeTab.value === 'learning') {
return '快去购买课程开始学习吧'
} else if (activeTab.value === 'completed') {
return '继续学习,完成更多课程'
}
return '快去探索更多课程吧'
}
const getMyCourses = () => {
// 根据activeTab确定state参数
let state = 1 // 默认学习中
if (activeTab.value === 'completed') {
state = 2 // 已学完
}
course_api.listMyExcellencourse(state, 1).then(res => {
console.log('API返回数据:', res)
if (res.code === 200 && res.data && res.data.list) {
// 将API数据转换为课程列表格式
const apiCourseList = res.data.list.map(item => ({
id: item.excellencourse_id,
title: item.excellencourse_title,
lessonCount: item.excellencourse_video_num,
status: item.excellencourse_upload_num === item.excellencourse_video_num ? '已完结' : '更新中',
learnedCount: item.study_num,
image: item.excellencourse_index_img || '/static/icon_home_my_patient.png',
tags: item.special_type_name ? [{ id: Date.now(), text: item.special_type_name }] : []
}))
// 根据当前标签页更新对应的课程列表
if (activeTab.value === 'learning') {
courseList.value.learning = apiCourseList
} else if (activeTab.value === 'completed') {
courseList.value.completed = apiCourseList
}
} else {
console.error('获取课程列表失败:', res.msg)
uni.showToast({
title: res.msg || '获取课程列表失败',
icon: 'none'
})
}
}).catch(err => {
console.error('API调用失败:', err)
uni.showToast({
title: '获取课程列表失败',
icon: 'none'
})
})
}
// 生命周期
onMounted(() => {
getSystemInfo()
getMyCourses()
})
</script>
<style lang="scss">
.my-courses-page {
min-height: 100vh;
background-color: #f5f5f5;
padding-bottom: 120rpx;
}
// 导航栏
.navbar {
position: fixed;
top: 0;
left: 0;
right: 0;
z-index: 999;
background-color: #fff;
border-bottom: 1rpx solid #e5e5e5;
.nav-content {
height: 88rpx;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 32rpx;
.nav-left, .nav-right {
width: 60rpx;
height: 60rpx;
display: flex;
align-items: center;
justify-content: center;
}
.nav-title {
font-size: 36rpx;
font-weight: 600;
color: #FF4757;
}
}
}
.page-content {
background-color: #f5f5f5;
}
// 标签导航
.tab-nav {
background-color: #fff;
display: flex;
align-items: center;
justify-content: center;
padding: 24rpx 0;
position: relative;
.tab-item {
padding: 16rpx 32rpx;
position: relative;
.tab-text {
font-size: 28rpx;
color: #999;
transition: color 0.3s;
}
&.active {
.tab-text {
color: #FF4757;
font-weight: 600;
}
}
}
.tab-divider {
width: 2rpx;
height: 32rpx;
background-color: #e0e0e0;
margin: 0 16rpx;
}
}
// 课程列表
.course-list {
padding: 24rpx;
.course-item {
background-color: #fff;
border-radius: 16rpx;
padding: 24rpx;
margin-bottom: 24rpx;
display: flex;
align-items: flex-start;
box-shadow: 0 2rpx 8rpx rgba(0,0,0,0.1);
.course-left {
margin-right: 24rpx;
.course-image {
width: 120rpx;
height: 120rpx;
border-radius: 12rpx;
}
}
.course-right {
flex: 1;
.course-title {
display: block;
font-size: 28rpx;
color: #333;
font-weight: 500;
line-height: 1.4;
margin-bottom: 16rpx;
// 文字溢出处理
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
}
.course-meta {
display: flex;
align-items: center;
margin-bottom: 16rpx;
.meta-text {
font-size: 24rpx;
color: #666;
}
.meta-separator {
font-size: 24rpx;
color: #999;
margin: 0 12rpx;
}
}
.course-tags {
display: flex;
gap: 12rpx;
.tag-item {
.tag-text {
background-color: #FF4757;
color: #fff;
font-size: 20rpx;
padding: 6rpx 12rpx;
border-radius: 8rpx;
}
}
}
}
}
}
// 空状态样式
.empty-state {
padding: 120rpx 0;
text-align: center;
.empty-icon {
margin-bottom: 32rpx;
}
.empty-title {
display: block;
font-size: 32rpx;
color: #999;
font-weight: 500;
margin-bottom: 16rpx;
}
.empty-desc {
display: block;
font-size: 26rpx;
color: #ccc;
line-height: 1.4;
}
}
// 订单记录浮动按钮
.floating-order {
position: fixed;
right: 24rpx;
bottom: 200rpx;
display: flex;
align-items: center;
gap: 12rpx;
background-color: #20B2AA;
padding: 16rpx 20rpx;
border-radius: 32rpx;
box-shadow: 0 4rpx 16rpx rgba(32, 178, 170, 0.3);
z-index: 999;
.order-icon {
width: 48rpx;
height: 48rpx;
background-color: rgba(255, 255, 255, 0.2);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
}
.order-text {
font-size: 24rpx;
color: #fff;
font-weight: 500;
}
}
// 底部导航栏
.bottom-nav {
position: fixed;
bottom: 0;
left: 0;
right: 0;
height: 120rpx;
background-color: #fff;
border-top: 1rpx solid #e5e5e5;
display: flex;
align-items: center;
z-index: 999;
.nav-item {
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 16rpx 0;
.nav-text {
font-size: 22rpx;
color: #999;
margin-top: 8rpx;
&.active {
color: #FF4757;
}
}
.nav-icon-active {
width: 48rpx;
height: 48rpx;
background-color: #FF4757;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
}
&.active {
.nav-text {
color: #FF4757;
}
}
}
}
</style>