1
This commit is contained in:
82
pages/course-detail/course-detail.js
Normal file
82
pages/course-detail/course-detail.js
Normal file
@@ -0,0 +1,82 @@
|
||||
// pages/course-detail/course-detail.js
|
||||
const { coursesData } = require('../../utils/data.js')
|
||||
const { showSuccess, showError } = require('../../utils/util.js')
|
||||
const learningTracker = require('../../utils/learningTracker.js')
|
||||
|
||||
Page({
|
||||
data: {
|
||||
course: null,
|
||||
isFavorite: false,
|
||||
activeTab: 0,
|
||||
tabs: ['课程信息', '教学大纲', '课程评价']
|
||||
},
|
||||
|
||||
onLoad(options) {
|
||||
const { id } = options
|
||||
this.loadCourseDetail(id)
|
||||
},
|
||||
|
||||
onShow() {
|
||||
// 开始跟踪学习时间
|
||||
learningTracker.onPageShow('course')
|
||||
},
|
||||
|
||||
onHide() {
|
||||
// 停止跟踪学习时间
|
||||
learningTracker.onPageHide()
|
||||
},
|
||||
|
||||
onUnload() {
|
||||
// 记录学习时长
|
||||
learningTracker.onPageUnload()
|
||||
},
|
||||
|
||||
// 加载课程详情
|
||||
loadCourseDetail(id) {
|
||||
const course = coursesData.find(c => c.id === parseInt(id))
|
||||
if (course) {
|
||||
const favorites = wx.getStorageSync('favoriteCourses') || []
|
||||
this.setData({
|
||||
course,
|
||||
isFavorite: favorites.includes(course.id)
|
||||
})
|
||||
} else {
|
||||
showError('课程不存在')
|
||||
setTimeout(() => {
|
||||
wx.navigateBack()
|
||||
}, 1500)
|
||||
}
|
||||
},
|
||||
|
||||
// 切换标签
|
||||
onTabChange(e) {
|
||||
const { index } = e.currentTarget.dataset
|
||||
this.setData({ activeTab: index })
|
||||
},
|
||||
|
||||
// 收藏/取消收藏
|
||||
onToggleFavorite() {
|
||||
const { course, isFavorite } = this.data
|
||||
let favorites = wx.getStorageSync('favoriteCourses') || []
|
||||
|
||||
if (isFavorite) {
|
||||
favorites = favorites.filter(id => id !== course.id)
|
||||
showSuccess('取消收藏')
|
||||
} else {
|
||||
favorites.push(course.id)
|
||||
showSuccess('收藏成功')
|
||||
}
|
||||
|
||||
wx.setStorageSync('favoriteCourses', favorites)
|
||||
this.setData({ isFavorite: !isFavorite })
|
||||
},
|
||||
|
||||
// 分享课程
|
||||
onShareAppMessage() {
|
||||
const { course } = this.data
|
||||
return {
|
||||
title: `推荐课程:${course.name}`,
|
||||
path: `/pages/course-detail/course-detail?id=${course.id}`
|
||||
}
|
||||
}
|
||||
})
|
||||
3
pages/course-detail/course-detail.json
Normal file
3
pages/course-detail/course-detail.json
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"navigationBarTitleText": "课程详情"
|
||||
}
|
||||
121
pages/course-detail/course-detail.wxml
Normal file
121
pages/course-detail/course-detail.wxml
Normal file
@@ -0,0 +1,121 @@
|
||||
<!--pages/course-detail/course-detail.wxml-->
|
||||
<view class="container" wx:if="{{course}}">
|
||||
<!-- 课程头部 -->
|
||||
<view class="course-header">
|
||||
<view class="course-name">{{course.name}}</view>
|
||||
<view class="course-meta">
|
||||
<text class="meta-tag">{{course.category}}</text>
|
||||
<text class="meta-tag">{{course.credit}}学分</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 基本信息卡片 -->
|
||||
<view class="info-card">
|
||||
<view class="info-row">
|
||||
<text class="info-icon">👨🏫</text>
|
||||
<view class="info-content">
|
||||
<text class="info-label">授课教师</text>
|
||||
<text class="info-value">{{course.teacher}}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="info-row">
|
||||
<text class="info-icon">🏫</text>
|
||||
<view class="info-content">
|
||||
<text class="info-label">开课院系</text>
|
||||
<text class="info-value">{{course.department}}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="info-row">
|
||||
<text class="info-icon">📍</text>
|
||||
<view class="info-content">
|
||||
<text class="info-label">上课地点</text>
|
||||
<text class="info-value">{{course.location}}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="info-row">
|
||||
<text class="info-icon">⏰</text>
|
||||
<view class="info-content">
|
||||
<text class="info-label">上课时间</text>
|
||||
<text class="info-value">{{course.time}}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="info-row">
|
||||
<text class="info-icon">👥</text>
|
||||
<view class="info-content">
|
||||
<text class="info-label">选课人数</text>
|
||||
<text class="info-value">{{course.enrolled}}/{{course.capacity}}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 标签栏 -->
|
||||
<view class="tab-bar">
|
||||
<view
|
||||
class="tab-item {{activeTab === index ? 'active' : ''}}"
|
||||
wx:for="{{tabs}}"
|
||||
wx:key="index"
|
||||
data-index="{{index}}"
|
||||
bindtap="onTabChange"
|
||||
>
|
||||
{{item}}
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 内容区域 -->
|
||||
<view class="content-area">
|
||||
<!-- 课程信息 -->
|
||||
<view class="tab-content" wx:if="{{activeTab === 0}}">
|
||||
<view class="section">
|
||||
<view class="section-title">课程简介</view>
|
||||
<view class="section-content">{{course.description}}</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 教学大纲 -->
|
||||
<view class="tab-content" wx:if="{{activeTab === 1}}">
|
||||
<view class="section">
|
||||
<view class="section-title">教学内容</view>
|
||||
<view class="syllabus-list">
|
||||
<view
|
||||
class="syllabus-item"
|
||||
wx:for="{{course.syllabus}}"
|
||||
wx:key="index"
|
||||
>
|
||||
<text class="syllabus-number">{{index + 1}}</text>
|
||||
<text class="syllabus-text">{{item}}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 课程评价 -->
|
||||
<view class="tab-content" wx:if="{{activeTab === 2}}">
|
||||
<view class="empty-tip">
|
||||
<text class="empty-icon">💬</text>
|
||||
<text class="empty-text">暂无评价,快来发表第一条评价吧</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 底部操作栏 -->
|
||||
<view class="action-bar">
|
||||
<button
|
||||
class="action-btn favorite-btn"
|
||||
bindtap="onToggleFavorite"
|
||||
>
|
||||
<text class="btn-icon">{{isFavorite ? '❤️' : '🤍'}}</text>
|
||||
<text>{{isFavorite ? '已收藏' : '收藏'}}</text>
|
||||
</button>
|
||||
<button
|
||||
class="action-btn share-btn"
|
||||
open-type="share"
|
||||
>
|
||||
<text class="btn-icon">📤</text>
|
||||
<text>分享</text>
|
||||
</button>
|
||||
</view>
|
||||
</view>
|
||||
220
pages/course-detail/course-detail.wxss
Normal file
220
pages/course-detail/course-detail.wxss
Normal file
@@ -0,0 +1,220 @@
|
||||
/* pages/course-detail/course-detail.wxss */
|
||||
.container {
|
||||
padding-bottom: 150rpx;
|
||||
}
|
||||
|
||||
/* 课程头部 */
|
||||
.course-header {
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
padding: 60rpx 30rpx 40rpx;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.course-name {
|
||||
font-size: 40rpx;
|
||||
font-weight: bold;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.course-meta {
|
||||
display: flex;
|
||||
gap: 15rpx;
|
||||
}
|
||||
|
||||
.meta-tag {
|
||||
padding: 8rpx 20rpx;
|
||||
background-color: rgba(255, 255, 255, 0.2);
|
||||
border-radius: 20rpx;
|
||||
font-size: 24rpx;
|
||||
}
|
||||
|
||||
/* 信息卡片 */
|
||||
.info-card {
|
||||
background-color: #ffffff;
|
||||
margin: 20rpx 30rpx;
|
||||
border-radius: 16rpx;
|
||||
padding: 30rpx;
|
||||
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
.info-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 20rpx 0;
|
||||
border-bottom: 1rpx solid #F5F5F5;
|
||||
}
|
||||
|
||||
.info-row:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.info-icon {
|
||||
font-size: 36rpx;
|
||||
margin-right: 20rpx;
|
||||
}
|
||||
|
||||
.info-content {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.info-label {
|
||||
font-size: 28rpx;
|
||||
color: #999999;
|
||||
}
|
||||
|
||||
.info-value {
|
||||
font-size: 28rpx;
|
||||
color: #333333;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
/* 标签栏 */
|
||||
.tab-bar {
|
||||
display: flex;
|
||||
background-color: #ffffff;
|
||||
margin: 0 30rpx;
|
||||
border-radius: 12rpx;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.tab-item {
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
padding: 25rpx 0;
|
||||
font-size: 28rpx;
|
||||
color: #666666;
|
||||
transition: all 0.3s;
|
||||
}
|
||||
|
||||
.tab-item.active {
|
||||
color: #4A90E2;
|
||||
font-weight: bold;
|
||||
background-color: #E8F4FF;
|
||||
}
|
||||
|
||||
/* 内容区域 */
|
||||
.content-area {
|
||||
margin: 20rpx 30rpx;
|
||||
}
|
||||
|
||||
.tab-content {
|
||||
background-color: #ffffff;
|
||||
border-radius: 16rpx;
|
||||
padding: 30rpx;
|
||||
}
|
||||
|
||||
.section {
|
||||
margin-bottom: 30rpx;
|
||||
}
|
||||
|
||||
.section:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
color: #333333;
|
||||
margin-bottom: 20rpx;
|
||||
padding-left: 20rpx;
|
||||
border-left: 6rpx solid #4A90E2;
|
||||
}
|
||||
|
||||
.section-content {
|
||||
font-size: 28rpx;
|
||||
color: #666666;
|
||||
line-height: 1.8;
|
||||
text-align: justify;
|
||||
}
|
||||
|
||||
/* 教学大纲 */
|
||||
.syllabus-list {
|
||||
padding-left: 10rpx;
|
||||
}
|
||||
|
||||
.syllabus-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 20rpx;
|
||||
margin-bottom: 15rpx;
|
||||
background-color: #F8F9FA;
|
||||
border-radius: 12rpx;
|
||||
}
|
||||
|
||||
.syllabus-number {
|
||||
width: 50rpx;
|
||||
height: 50rpx;
|
||||
line-height: 50rpx;
|
||||
text-align: center;
|
||||
background-color: #4A90E2;
|
||||
color: #ffffff;
|
||||
border-radius: 25rpx;
|
||||
font-size: 24rpx;
|
||||
margin-right: 20rpx;
|
||||
}
|
||||
|
||||
.syllabus-text {
|
||||
flex: 1;
|
||||
font-size: 28rpx;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
/* 空状态 */
|
||||
.empty-tip {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 80rpx 0;
|
||||
}
|
||||
|
||||
.empty-icon {
|
||||
font-size: 100rpx;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.empty-text {
|
||||
font-size: 26rpx;
|
||||
color: #999999;
|
||||
}
|
||||
|
||||
/* 底部操作栏 */
|
||||
.action-bar {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
display: flex;
|
||||
gap: 20rpx;
|
||||
padding: 20rpx 30rpx;
|
||||
padding-bottom: calc(20rpx + env(safe-area-inset-bottom));
|
||||
background-color: #ffffff;
|
||||
box-shadow: 0 -4rpx 20rpx rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
.action-btn {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 90rpx;
|
||||
border-radius: 45rpx;
|
||||
font-size: 28rpx;
|
||||
gap: 10rpx;
|
||||
}
|
||||
|
||||
.favorite-btn {
|
||||
background-color: #FFE8E8;
|
||||
color: #FF6B6B;
|
||||
}
|
||||
|
||||
.share-btn {
|
||||
background-color: #E8F4FF;
|
||||
color: #4A90E2;
|
||||
}
|
||||
|
||||
.btn-icon {
|
||||
font-size: 32rpx;
|
||||
}
|
||||
Reference in New Issue
Block a user