Browse Source

feat: tabBar课程直进课程主页,支持报名/进班/课程内容一站式

liaoxg 1 week ago
parent
commit
9666a38

+ 1 - 1
train-frontend/pages.json

@@ -196,7 +196,7 @@
         "selectedIconPath": "static/tab-task-active.png"
       },
       {
-        "pagePath": "pages/course/index",
+        "pagePath": "pages/course/detail",
         "text": "课程",
         "iconPath": "static/tab-course.png",
         "selectedIconPath": "static/tab-course-active.png"

+ 87 - 4
train-frontend/pages/course/detail.vue

@@ -9,8 +9,42 @@
       <text class="course-class" v-if="className">我的班次:{{ className }}</text>
     </view>
 
+    <!-- 报名/参加课程操作区 -->
+    <view class="action-card" v-if="enrollmentStatus !== 'confirmed'">
+      <!-- 未报名 -->
+      <template v-if="enrollmentStatus === 'none'">
+        <text class="action-title">报名参加本课程</text>
+        <text class="action-desc">填写报名信息并支付后即可申请进班学习</text>
+        <button class="action-btn" @click="goTo('/pages/enroll/list')">去报名</button>
+      </template>
+      <!-- 待支付 -->
+      <template v-else-if="enrollmentStatus === 'pending'">
+        <text class="action-title">报名待支付</text>
+        <text class="action-desc">完成支付后即可申请进班</text>
+        <button class="action-btn" @click="goTo('/pages/enroll/list')">去支付</button>
+      </template>
+      <!-- 已支付待进班 -->
+      <template v-else-if="enrollmentStatus === 'paid'">
+        <text class="action-title">已报名,待进班</text>
+        <text class="action-desc">提交进班申请后由班主任审核,审核通过即可开始学习</text>
+        <button class="action-btn" :disabled="enterLoading" @click="applyEnter">申请进班</button>
+      </template>
+      <!-- 审核中 -->
+      <template v-else-if="enrollmentStatus === 'reviewing'">
+        <text class="action-title">进班审核中</text>
+        <text class="action-desc">班主任正在审核你的进班申请,请耐心等待</text>
+        <button class="action-btn disabled" disabled>审核中</button>
+      </template>
+      <!-- 已驳回 -->
+      <template v-else-if="enrollmentStatus === 'rejected'">
+        <text class="action-title">进班申请被驳回</text>
+        <text class="action-desc">可重新提交进班申请,或联系班主任了解原因</text>
+        <button class="action-btn" :disabled="enterLoading" @click="applyEnter">重新申请进班</button>
+      </template>
+    </view>
+
     <!-- 学习进度 -->
-    <view class="section-card">
+    <view class="section-card" v-if="enrollmentStatus === 'confirmed'">
       <view class="section-head">
         <text class="section-title">学习进度</text>
         <text class="progress-count">{{ progress.done }}/{{ progress.total }} 项完成</text>
@@ -27,7 +61,8 @@
     </view>
 
     <!-- 课程内功能入口 -->
-    <view class="section-title">课程内容</view>
+    <view v-if="enrollmentStatus === 'confirmed'">
+      <view class="section-title">课程内容</view>
     <view class="nav-grid">
       <view class="nav-item" @click="goTo('/pages/material/index')">
         <text class="nav-icon">📄</text>
@@ -70,18 +105,21 @@
         <text class="nav-text">三本账</text>
       </view>
     </view>
+    </view>
   </view>
 </template>
 
 <script>
-import { getMyCourse, getCourseProgress } from '@/utils/api.js'
+import { getMyCourse, getCourseProgress, enterCourse } from '@/utils/api.js'
 
 export default {
   data() {
     return {
       course: {},
       className: '',
-      progress: { done: 0, total: 0, items: [] }
+      enrollment: null,
+      progress: { done: 0, total: 0, items: [] },
+      enterLoading: false
     }
   },
   computed: {
@@ -90,6 +128,10 @@ export default {
       if (!total) return '0%'
       var pct = Math.round((this.progress.done || 0) * 100 / total)
       return pct + '%'
+    },
+    enrollmentStatus() {
+      if (!this.enrollment || !this.enrollment.status) return 'none'
+      return this.enrollment.status
     }
   },
   onLoad() {
@@ -103,6 +145,7 @@ export default {
         var c = d.course || {}
         self.course = c
         self.className = d.className || ''
+        self.enrollment = d.enrollment || null
       }).catch(function() {})
       getCourseProgress().then(function(resp) {
         var d = resp.data || {}
@@ -113,6 +156,40 @@ export default {
         }
       }).catch(function() {})
     },
+    applyEnter() {
+      var self = this
+      if (!self.course.id) return
+      uni.showModal({
+        title: '申请进班',
+        content: '确认提交进班申请?提交后由班主任审核。',
+        success: function(res) {
+          if (!res.confirm) return
+          self.enterLoading = true
+          enterCourse(self.course.id).then(function(resp) {
+            uni.showToast({ title: '已提交申请', icon: 'success' })
+            self.loadAll()
+          }).catch(function(err) {
+            var msg = (err && err.message) || '提交失败'
+            if (msg.indexOf('报名') >= 0 || msg.indexOf('支付') >= 0) {
+              uni.showModal({
+                title: '提示',
+                content: msg,
+                confirmText: '去报名',
+                success: function(r) {
+                  if (r.confirm) {
+                    uni.navigateTo({ url: '/pages/enroll/list' })
+                  }
+                }
+              })
+            } else {
+              uni.showToast({ title: msg, icon: 'none' })
+            }
+          }).finally(function() {
+            self.enterLoading = false
+          })
+        }
+      })
+    },
     statusLabel(st) {
       var map = { upcoming: '未开始', active: '进行中', finished: '已结束', draft: '未发布' }
       return map[st] || st || '-'
@@ -130,6 +207,12 @@ export default {
 <style scoped>
 .course-detail-page { min-height: 100vh; background: #F5F5F5; padding: 24rpx 32rpx; }
 .course-head { background: #FFF; border-radius: 20rpx; padding: 32rpx; margin-bottom: 24rpx; display: flex; flex-direction: column; }
+.action-card { background: #FFF; border-radius: 16rpx; padding: 32rpx; margin-bottom: 24rpx; display: flex; flex-direction: column; align-items: center; }
+.action-title { font-size: 32rpx; font-weight: 700; color: #1E293B; margin-bottom: 12rpx; }
+.action-desc { font-size: 26rpx; color: #64748B; text-align: center; line-height: 1.6; margin-bottom: 28rpx; }
+.action-btn { width: 100%; height: 88rpx; line-height: 88rpx; background: linear-gradient(135deg, #F97316, #EA580C); color: #FFF; font-size: 30rpx; font-weight: 600; border-radius: 44rpx; border: none; }
+.action-btn.disabled { background: #F1F5F9; color: #94A3B8; }
+.action-btn:active { opacity: 0.88; }
 .course-level { align-self: flex-start; font-size: 22rpx; font-weight: 600; color: #F97316; background: #FFF7ED; border-radius: 8rpx; padding: 4rpx 14rpx; margin-bottom: 12rpx; }
 .course-name { font-size: 36rpx; font-weight: 700; color: #1E293B; margin-bottom: 8rpx; }
 .course-status { align-self: flex-start; font-size: 22rpx; border-radius: 6rpx; padding: 4rpx 16rpx; margin-bottom: 12rpx; }

+ 1 - 1
train-frontend/pages/course/index.vue

@@ -103,7 +103,7 @@ export default {
       if (!c) return
       var s = c.myStatus
       if (s === 'confirmed') {
-        uni.navigateTo({ url: '/pages/course/detail?courseId=' + c.id })
+        uni.switchTab({ url: '/pages/course/detail' })
       } else if (s === 'pending') {
         uni.navigateTo({ url: '/pages/enroll/list' })
       } else if (s === 'paid' || s === 'rejected') {

+ 2 - 2
train-frontend/pages/index/index.vue

@@ -26,7 +26,7 @@
 
     <view class="section-title">日常服务</view>
     <view class="nav-grid">
-      <view class="nav-item" @click="switchToTab('/pages/course/index')">
+      <view class="nav-item" @click="switchToTab('/pages/course/detail')">
         <text class="nav-icon">📚</text>
         <text class="nav-text">课程</text>
       </view>
@@ -44,7 +44,7 @@
       </view>
     </view>
 
-    <view class="course-hint" @click="switchToTab('/pages/course/index')">
+    <view class="course-hint" @click="switchToTab('/pages/course/detail')">
       <text class="course-hint-icon">📖</text>
       <view class="course-hint-text">
         <text class="course-hint-title">{{ courseLabel }} 课程内容</text>

+ 1 - 1
train-frontend/pages/login/index.vue

@@ -59,7 +59,7 @@ export default {
               if (!data.alumniVerify || data.alumniVerify === 'pending') {
                 uni.redirectTo({ url: '/pages/verify/index' })
               } else if (!data.classId) {
-                uni.switchTab({ url: '/pages/course/index' })
+                uni.switchTab({ url: '/pages/course/detail' })
               } else {
                 uni.switchTab({ url: '/pages/index/index' })
               }

+ 1 - 1
train-frontend/pages/mine/index.vue

@@ -76,7 +76,7 @@
       </view>
     </view>
 
-    <view class="course-entry" @click="switchToTab('/pages/course/index')">
+    <view class="course-entry" @click="switchToTab('/pages/course/detail')">
       <text class="course-entry-icon">📖</text>
       <view class="course-entry-text">
         <text class="course-entry-title">课程内容</text>

+ 1 - 1
train-frontend/pages/verify/index.vue

@@ -108,7 +108,7 @@ export default {
           uni.showToast({ title: '校验通过', icon: 'success' })
           setTimeout(function() {
 if (!self.$store.state.classId) {
-              uni.switchTab({ url: '/pages/course/index' })
+              uni.switchTab({ url: '/pages/course/detail' })
             } else {
               uni.switchTab({ url: '/pages/index/index' })
             }