refactor(router): 重构路由配置并删除无用文件
重构了路由配置文件,更新了路由路径和组件名称,并添加了元数据。删除了不再使用的About.vue文件,同时新增了CoursesPage.vue页面。
Showing
5 changed files
with
469 additions
and
77 deletions
| 1 | +/* | ||
| 2 | + * @Date: 2025-03-20 20:36:36 | ||
| 3 | + * @LastEditors: hookehuyr hookehuyr@gmail.com | ||
| 4 | + * @LastEditTime: 2025-03-20 20:50:41 | ||
| 5 | + * @FilePath: /mlaj/src/router/index.js | ||
| 6 | + * @Description: 文件描述 | ||
| 7 | + */ | ||
| 1 | import { createRouter, createWebHistory } from 'vue-router' | 8 | import { createRouter, createWebHistory } from 'vue-router' |
| 2 | 9 | ||
| 3 | const routes = [ | 10 | const routes = [ |
| 4 | { | 11 | { |
| 5 | path: '/', | 12 | path: '/', |
| 6 | - name: 'home', | 13 | + name: 'HomePage', |
| 7 | - component: () => import('../views/Home.vue') | 14 | + component: () => import('../views/HomePage.vue'), |
| 15 | + meta: { title: 'HomePage' }, | ||
| 8 | }, | 16 | }, |
| 9 | { | 17 | { |
| 10 | - path: '/about', | 18 | + path: '/courses', |
| 11 | - name: 'about', | 19 | + name: 'Courses', |
| 12 | - component: () => import('../views/About.vue') | 20 | + component: () => import('../views/courses/CoursesPage.vue'), |
| 13 | - } | 21 | + meta: { title: 'Courses' }, |
| 22 | + }, | ||
| 23 | + { | ||
| 24 | + path: '/courses/:id', | ||
| 25 | + name: 'CourseDetail', | ||
| 26 | + component: () => import('../views/courses/CourseDetailPage.vue'), | ||
| 27 | + meta: { title: 'CourseDetail' }, | ||
| 28 | + }, | ||
| 14 | ] | 29 | ] |
| 15 | 30 | ||
| 16 | const router = createRouter({ | 31 | const router = createRouter({ |
| 17 | history: createWebHistory(), | 32 | history: createWebHistory(), |
| 18 | - routes | 33 | + routes, |
| 19 | }) | 34 | }) |
| 20 | 35 | ||
| 21 | export default router | 36 | export default router | ... | ... |
src/views/About.vue
deleted
100644 → 0
| 1 | -<script setup> | ||
| 2 | -import { Button, NavBar, Tabbar, TabbarItem } from 'vant'; | ||
| 3 | -</script> | ||
| 4 | - | ||
| 5 | -<template> | ||
| 6 | - <div class="min-h-screen flex flex-col bg-gray-100"> | ||
| 7 | - <van-nav-bar | ||
| 8 | - title="关于" | ||
| 9 | - left-text="返回" | ||
| 10 | - right-text="菜单" | ||
| 11 | - left-arrow | ||
| 12 | - @click-left="onClickLeft" | ||
| 13 | - @click-right="onClickRight" | ||
| 14 | - /> | ||
| 15 | - | ||
| 16 | - <div class="flex-1 p-4"> | ||
| 17 | - <div class="bg-white rounded-lg shadow p-4 mb-4"> | ||
| 18 | - <h2 class="text-xl font-bold mb-2">关于我们</h2> | ||
| 19 | - <p class="text-gray-600 mb-4">这是一个示例项目的关于页面,展示了如何使用Vue3、Vite、Vant4和TailwindCSS构建现代化的Web应用。</p> | ||
| 20 | - <van-button type="primary" block>了解更多</van-button> | ||
| 21 | - </div> | ||
| 22 | - | ||
| 23 | - <div class="grid grid-cols-2 gap-4"> | ||
| 24 | - <div class="bg-white rounded-lg shadow p-4"> | ||
| 25 | - <h3 class="text-lg font-semibold mb-2">联系方式</h3> | ||
| 26 | - <ul class="text-gray-600"> | ||
| 27 | - <li>邮箱:example@example.com</li> | ||
| 28 | - <li>电话:123-456-7890</li> | ||
| 29 | - <li>地址:示例地址</li> | ||
| 30 | - </ul> | ||
| 31 | - </div> | ||
| 32 | - <div class="bg-white rounded-lg shadow p-4"> | ||
| 33 | - <h3 class="text-lg font-semibold mb-2">版本信息</h3> | ||
| 34 | - <ul class="text-gray-600"> | ||
| 35 | - <li>当前版本:1.0.0</li> | ||
| 36 | - <li>更新日期:2024-03-20</li> | ||
| 37 | - <li>开源协议:MIT</li> | ||
| 38 | - </ul> | ||
| 39 | - </div> | ||
| 40 | - </div> | ||
| 41 | - </div> | ||
| 42 | - | ||
| 43 | - <van-tabbar v-model="active"> | ||
| 44 | - <van-tabbar-item icon="home-o">首页</van-tabbar-item> | ||
| 45 | - <van-tabbar-item icon="search">搜索</van-tabbar-item> | ||
| 46 | - <van-tabbar-item icon="friends-o">好友</van-tabbar-item> | ||
| 47 | - <van-tabbar-item icon="setting-o">设置</van-tabbar-item> | ||
| 48 | - </van-tabbar> | ||
| 49 | - </div> | ||
| 50 | -</template> | ||
| 51 | - | ||
| 52 | -<script> | ||
| 53 | -export default { | ||
| 54 | - data() { | ||
| 55 | - return { | ||
| 56 | - active: 0 | ||
| 57 | - } | ||
| 58 | - }, | ||
| 59 | - methods: { | ||
| 60 | - onClickLeft() { | ||
| 61 | - this.$router.back() | ||
| 62 | - }, | ||
| 63 | - onClickRight() { | ||
| 64 | - // 处理右侧按钮点击 | ||
| 65 | - } | ||
| 66 | - } | ||
| 67 | -} | ||
| 68 | -</script> |
| 1 | <!-- | 1 | <!-- |
| 2 | * @Date: 2025-03-20 19:55:21 | 2 | * @Date: 2025-03-20 19:55:21 |
| 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com | 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com |
| 4 | - * @LastEditTime: 2025-03-20 20:26:17 | 4 | + * @LastEditTime: 2025-03-20 20:48:08 |
| 5 | - * @FilePath: /vue-vite/src/views/Home.vue | 5 | + * @FilePath: /mlaj/src/views/HomePage.vue |
| 6 | * @Description: 文件描述 | 6 | * @Description: 文件描述 |
| 7 | --> | 7 | --> |
| 8 | <template> | 8 | <template> | ... | ... |
src/views/courses/CourseDetailPage.vue
0 → 100644
| 1 | +<template> | ||
| 2 | + <AppLayout title="课程详情" showBackButton :rightContent="rightContent"> | ||
| 3 | + <div class="pb-24"> | ||
| 4 | + <!-- Course Header --> | ||
| 5 | + <div class="bg-gradient-to-b from-red-500 to-red-600 p-4 mb-4 rounded-b-3xl shadow-lg"> | ||
| 6 | + <div class="bg-white/10 backdrop-blur-sm rounded-lg p-3 mb-3 inline-block"> | ||
| 7 | + <div class="text-white font-semibold">{{ course?.subtitle?.split(' ')[0] }}</div> | ||
| 8 | + </div> | ||
| 9 | + <h1 class="text-2xl text-white font-bold mb-1">{{ course?.title }}</h1> | ||
| 10 | + <h2 class="text-lg text-white/90">{{ course?.subtitle }}</h2> | ||
| 11 | + <div class="mt-4 flex justify-between items-center"> | ||
| 12 | + <div class="text-orange-300 font-bold text-2xl">¥{{ course?.price }}</div> | ||
| 13 | + <div class="bg-orange-500/30 text-orange-100 text-xs px-3 py-1 rounded-full"> | ||
| 14 | + 限时优惠 | ||
| 15 | + </div> | ||
| 16 | + </div> | ||
| 17 | + <div class="flex justify-between text-xs text-white/80 mt-3"> | ||
| 18 | + <div>已更新{{ course?.updatedLessons }}期</div> | ||
| 19 | + <div>{{ course?.subscribers }}人订阅</div> | ||
| 20 | + </div> | ||
| 21 | + <div v-if="course?.expireDate" class="text-xs text-white/80 mt-1"> | ||
| 22 | + 有效期: {{ course?.expireDate }} | ||
| 23 | + </div> | ||
| 24 | + </div> | ||
| 25 | + | ||
| 26 | + <!-- Course Main Content --> | ||
| 27 | + <div class="px-4"> | ||
| 28 | + <!-- Course Details --> | ||
| 29 | + <FrostedGlass class="mb-4 p-4 rounded-xl"> | ||
| 30 | + <h3 class="text-lg font-bold text-gray-800 mb-3">本课程介绍</h3> | ||
| 31 | + <p class="text-gray-700 whitespace-pre-line"> | ||
| 32 | + {{ course?.description }} | ||
| 33 | + </p> | ||
| 34 | + </FrostedGlass> | ||
| 35 | + | ||
| 36 | + <!-- Course Image --> | ||
| 37 | + <div class="mb-6"> | ||
| 38 | + <img | ||
| 39 | + :src="course?.imageUrl" | ||
| 40 | + :alt="course?.title" | ||
| 41 | + class="w-full h-auto rounded-xl shadow-md" | ||
| 42 | + /> | ||
| 43 | + </div> | ||
| 44 | + | ||
| 45 | + <!-- Tab Navigation --> | ||
| 46 | + <FrostedGlass class="mb-6 rounded-xl overflow-hidden"> | ||
| 47 | + <div class="border-b border-gray-200"> | ||
| 48 | + <div class="flex"> | ||
| 49 | + <button | ||
| 50 | + v-for="(item, index) in curriculumItems" | ||
| 51 | + :key="index" | ||
| 52 | + @click="activeTab = item.title" | ||
| 53 | + :class="[ | ||
| 54 | + 'flex-1 py-3 font-medium text-center', | ||
| 55 | + activeTab === item.title | ||
| 56 | + ? 'text-green-600 border-b-2 border-green-600 bg-green-50/50' | ||
| 57 | + : 'text-gray-500' | ||
| 58 | + ]" | ||
| 59 | + > | ||
| 60 | + {{ item.title }} | ||
| 61 | + </button> | ||
| 62 | + </div> | ||
| 63 | + </div> | ||
| 64 | + | ||
| 65 | + <!-- Tab Content --> | ||
| 66 | + <div class="p-4"> | ||
| 67 | + <div v-if="activeTab === '课程特色'"> | ||
| 68 | + <ul class="list-disc pl-5 space-y-2 text-gray-700"> | ||
| 69 | + <li>小班授课,更多关注</li> | ||
| 70 | + <li>名师授课,经验丰富</li> | ||
| 71 | + <li>随堂练习,巩固知识</li> | ||
| 72 | + <li>及时反馈,调整教学</li> | ||
| 73 | + </ul> | ||
| 74 | + </div> | ||
| 75 | + | ||
| 76 | + <div v-if="activeTab === '课程大纲'"> | ||
| 77 | + <div class="space-y-4"> | ||
| 78 | + <div class="border-l-2 border-green-500 pl-3"> | ||
| 79 | + <h4 class="font-medium text-gray-800">第一章:心态准备</h4> | ||
| 80 | + <p class="text-sm text-gray-600 mt-1">45分钟 · 3个小节</p> | ||
| 81 | + </div> | ||
| 82 | + <div class="border-l-2 border-gray-300 pl-3"> | ||
| 83 | + <h4 class="font-medium text-gray-800">第二章:考前减压</h4> | ||
| 84 | + <p class="text-sm text-gray-600 mt-1">60分钟 · 4个小节</p> | ||
| 85 | + </div> | ||
| 86 | + <div class="border-l-2 border-gray-300 pl-3"> | ||
| 87 | + <h4 class="font-medium text-gray-800">第三章:家庭支持</h4> | ||
| 88 | + <p class="text-sm text-gray-600 mt-1">50分钟 · 3个小节</p> | ||
| 89 | + </div> | ||
| 90 | + </div> | ||
| 91 | + </div> | ||
| 92 | + | ||
| 93 | + <div v-if="activeTab === '课程亮点'"> | ||
| 94 | + <div class="space-y-3 text-gray-700"> | ||
| 95 | + <p>✓ 专业的心理辅导</p> | ||
| 96 | + <p>✓ 系统化的学习方法</p> | ||
| 97 | + <p>✓ 实用的家庭沟通技巧</p> | ||
| 98 | + <p>✓ 定制的减压活动推荐</p> | ||
| 99 | + </div> | ||
| 100 | + </div> | ||
| 101 | + | ||
| 102 | + <div v-if="activeTab === '学习目标'"> | ||
| 103 | + <div class="space-y-3 text-gray-700"> | ||
| 104 | + <p>1. 帮助家长理解考前压力来源</p> | ||
| 105 | + <p>2. 掌握有效的情绪管理技巧</p> | ||
| 106 | + <p>3. 建立积极的家庭支持系统</p> | ||
| 107 | + <p>4. 培养考前良好的心态和信心</p> | ||
| 108 | + </div> | ||
| 109 | + </div> | ||
| 110 | + </div> | ||
| 111 | + </FrostedGlass> | ||
| 112 | + | ||
| 113 | + <!-- Teacher Introduction --> | ||
| 114 | + <FrostedGlass class="mb-6 p-4 rounded-xl"> | ||
| 115 | + <h3 class="text-lg font-bold text-gray-800 mb-3">主讲老师</h3> | ||
| 116 | + <div class="flex items-center"> | ||
| 117 | + <div class="w-16 h-16 rounded-full overflow-hidden mr-4"> | ||
| 118 | + <img | ||
| 119 | + src="https://cdn.ipadbiz.cn/mlaj/images/teacher-avatar.jpg" | ||
| 120 | + alt="Teacher" | ||
| 121 | + class="w-full h-full object-cover" | ||
| 122 | + @error="handleImageError" | ||
| 123 | + /> | ||
| 124 | + </div> | ||
| 125 | + <div> | ||
| 126 | + <h4 class="font-bold text-gray-900">张明睿</h4> | ||
| 127 | + <p class="text-sm text-gray-600">教育心理学博士</p> | ||
| 128 | + <p class="text-xs text-gray-500 mt-1">10年家庭教育培训经验</p> | ||
| 129 | + </div> | ||
| 130 | + </div> | ||
| 131 | + </FrostedGlass> | ||
| 132 | + | ||
| 133 | + <!-- Student Reviews --> | ||
| 134 | + <FrostedGlass class="mb-6 p-4 rounded-xl"> | ||
| 135 | + <h3 class="text-lg font-bold text-gray-800 mb-3">学员评价</h3> | ||
| 136 | + <div class="flex items-center mb-3"> | ||
| 137 | + <div class="flex text-yellow-400 mr-2"> | ||
| 138 | + <svg | ||
| 139 | + v-for="star in 5" | ||
| 140 | + :key="star" | ||
| 141 | + xmlns="http://www.w3.org/2000/svg" | ||
| 142 | + class="h-5 w-5" | ||
| 143 | + viewBox="0 0 20 20" | ||
| 144 | + fill="currentColor" | ||
| 145 | + > | ||
| 146 | + <path | ||
| 147 | + d="M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z" | ||
| 148 | + /> | ||
| 149 | + </svg> | ||
| 150 | + </div> | ||
| 151 | + <div class="text-gray-700">4.9 (126条评论)</div> | ||
| 152 | + </div> | ||
| 153 | + | ||
| 154 | + <div class="space-y-4"> | ||
| 155 | + <div class="border-b border-gray-100 pb-3"> | ||
| 156 | + <div class="flex justify-between"> | ||
| 157 | + <div class="font-medium text-gray-800">王小明</div> | ||
| 158 | + <div class="text-xs text-gray-500">2024-06-15</div> | ||
| 159 | + </div> | ||
| 160 | + <p class="text-sm text-gray-600 mt-1"> | ||
| 161 | + 课程内容非常实用,老师讲解清晰,帮助我和孩子度过了考前紧张期。 | ||
| 162 | + </p> | ||
| 163 | + </div> | ||
| 164 | + | ||
| 165 | + <div class="border-b border-gray-100 pb-3"> | ||
| 166 | + <div class="flex justify-between"> | ||
| 167 | + <div class="font-medium text-gray-800">李晓华</div> | ||
| 168 | + <div class="text-xs text-gray-500">2024-06-10</div> | ||
| 169 | + </div> | ||
| 170 | + <p class="text-sm text-gray-600 mt-1"> | ||
| 171 | + 老师提供的减压方法很有效,孩子学习状态明显改善,感谢这个课程! | ||
| 172 | + </p> | ||
| 173 | + </div> | ||
| 174 | + </div> | ||
| 175 | + | ||
| 176 | + <button class="w-full text-center text-green-600 mt-3 text-sm"> | ||
| 177 | + 查看全部评价 | ||
| 178 | + </button> | ||
| 179 | + </FrostedGlass> | ||
| 180 | + </div> | ||
| 181 | + | ||
| 182 | + <!-- Bottom Action Bar --> | ||
| 183 | + <div class="fixed bottom-16 left-0 right-0 bg-white shadow-lg p-3 flex justify-between items-center"> | ||
| 184 | + <div class="flex space-x-4"> | ||
| 185 | + <button class="flex flex-col items-center text-gray-500 text-xs"> | ||
| 186 | + <svg | ||
| 187 | + xmlns="http://www.w3.org/2000/svg" | ||
| 188 | + class="h-6 w-6" | ||
| 189 | + fill="none" | ||
| 190 | + viewBox="0 0 24 24" | ||
| 191 | + stroke="currentColor" | ||
| 192 | + > | ||
| 193 | + <path | ||
| 194 | + stroke-linecap="round" | ||
| 195 | + stroke-linejoin="round" | ||
| 196 | + stroke-width="2" | ||
| 197 | + d="M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z" | ||
| 198 | + /> | ||
| 199 | + </svg> | ||
| 200 | + 咨询 | ||
| 201 | + </button> | ||
| 202 | + <button class="flex flex-col items-center text-gray-500 text-xs"> | ||
| 203 | + <svg | ||
| 204 | + xmlns="http://www.w3.org/2000/svg" | ||
| 205 | + class="h-6 w-6" | ||
| 206 | + fill="none" | ||
| 207 | + viewBox="0 0 24 24" | ||
| 208 | + stroke="currentColor" | ||
| 209 | + > | ||
| 210 | + <path | ||
| 211 | + stroke-linecap="round" | ||
| 212 | + stroke-linejoin="round" | ||
| 213 | + stroke-width="2" | ||
| 214 | + d="M8.684 13.342C8.886 12.938 9 12.482 9 12c0-.482-.114-.938-.316-1.342m0 2.684a3 3 0 110-2.684m0 2.684l6.632 3.316m-6.632-6l6.632-3.316m0 0a3 3 0 105.367-2.684 3 3 0 00-5.367 2.684zm0 9.316a3 3 0 105.368 2.684 3 3 0 00-5.368-2.684z" | ||
| 215 | + /> | ||
| 216 | + </svg> | ||
| 217 | + 分享 | ||
| 218 | + </button> | ||
| 219 | + <button class="flex flex-col items-center text-gray-500 text-xs"> | ||
| 220 | + <svg | ||
| 221 | + xmlns="http://www.w3.org/2000/svg" | ||
| 222 | + class="h-6 w-6" | ||
| 223 | + fill="none" | ||
| 224 | + viewBox="0 0 24 24" | ||
| 225 | + stroke="currentColor" | ||
| 226 | + > | ||
| 227 | + <path | ||
| 228 | + stroke-linecap="round" | ||
| 229 | + stroke-linejoin="round" | ||
| 230 | + stroke-width="2" | ||
| 231 | + d="M4.318 6.318a4.5 4.5 0 000 6.364L12 20.364l7.682-7.682a4.5 4.5 0 00-6.364-6.364L12 7.636l-1.318-1.318a4.5 4.5 0 00-6.364 0z" | ||
| 232 | + /> | ||
| 233 | + </svg> | ||
| 234 | + 收藏 | ||
| 235 | + </button> | ||
| 236 | + </div> | ||
| 237 | + <div class="flex items-center"> | ||
| 238 | + <div class="mr-2"> | ||
| 239 | + <div class="text-red-500 font-bold">¥{{ course?.price }}</div> | ||
| 240 | + <div class="text-xs text-gray-400 line-through"> | ||
| 241 | + ¥{{ Math.round(course?.price * 1.2) }} | ||
| 242 | + </div> | ||
| 243 | + </div> | ||
| 244 | + <button class="bg-gradient-to-r from-green-500 to-green-600 text-white px-6 py-2 rounded-full text-sm font-medium shadow-md"> | ||
| 245 | + 立即购买 | ||
| 246 | + </button> | ||
| 247 | + </div> | ||
| 248 | + </div> | ||
| 249 | + </div> | ||
| 250 | + </AppLayout> | ||
| 251 | +</template> | ||
| 252 | + | ||
| 253 | +<script setup lang="jsx"> | ||
| 254 | +import { ref, onMounted, defineComponent, h } from 'vue' | ||
| 255 | +import { useRoute, useRouter } from 'vue-router' | ||
| 256 | +import AppLayout from '@/components/layout/AppLayout.vue' | ||
| 257 | +import FrostedGlass from '@/components/ui/FrostedGlass.vue' | ||
| 258 | +import { courses } from '@/utils/mockData' | ||
| 259 | + | ||
| 260 | +const route = useRoute() | ||
| 261 | +const router = useRouter() | ||
| 262 | +const course = ref(null) | ||
| 263 | +const activeTab = ref('课程特色') | ||
| 264 | + | ||
| 265 | +// Curriculum items | ||
| 266 | +const curriculumItems = [ | ||
| 267 | + { title: '课程特色', active: true }, | ||
| 268 | + { title: '课程大纲', active: false }, | ||
| 269 | + { title: '课程亮点', active: false }, | ||
| 270 | + { title: '学习目标', active: false }, | ||
| 271 | +] | ||
| 272 | + | ||
| 273 | +// Handle image error | ||
| 274 | +const handleImageError = (e) => { | ||
| 275 | + e.target.src = 'https://via.placeholder.com/150?text=Teacher' | ||
| 276 | +} | ||
| 277 | + | ||
| 278 | +// Right content component | ||
| 279 | +const RightContent = defineComponent({ | ||
| 280 | + setup() { | ||
| 281 | + return () => ( | ||
| 282 | + <button class="p-2"> | ||
| 283 | + <svg | ||
| 284 | + xmlns="http://www.w3.org/2000/svg" | ||
| 285 | + class="h-6 w-6 text-gray-700" | ||
| 286 | + fill="none" | ||
| 287 | + viewBox="0 0 24 24" | ||
| 288 | + stroke="currentColor" | ||
| 289 | + > | ||
| 290 | + <path | ||
| 291 | + stroke-linecap="round" | ||
| 292 | + stroke-linejoin="round" | ||
| 293 | + stroke-width="2" | ||
| 294 | + d="M12 5v.01M12 12v.01M12 19v.01M12 6a1 1 0 110-2 1 1 0 010 2zm0 7a1 1 0 110-2 1 1 0 010 2zm0 7a1 1 0 110-2 1 1 0 010 2z" | ||
| 295 | + /> | ||
| 296 | + </svg> | ||
| 297 | + </button> | ||
| 298 | + ) | ||
| 299 | + }, | ||
| 300 | +}) | ||
| 301 | + | ||
| 302 | +const rightContent = h(RightContent) | ||
| 303 | + | ||
| 304 | +// Fetch course data | ||
| 305 | +onMounted(() => { | ||
| 306 | + const id = route.params.id | ||
| 307 | + const foundCourse = courses.find(c => c.id === id) | ||
| 308 | + if (foundCourse) { | ||
| 309 | + course.value = foundCourse | ||
| 310 | + } else { | ||
| 311 | + // Course not found, redirect to courses page | ||
| 312 | + router.push('/courses') | ||
| 313 | + } | ||
| 314 | +}) | ||
| 315 | +</script> |
src/views/courses/CoursesPage.vue
0 → 100644
| 1 | +<template> | ||
| 2 | + <AppLayout title="课程" :rightContent="rightContent"> | ||
| 3 | + <div class="pb-16"> | ||
| 4 | + <!-- Search Bar --> | ||
| 5 | + <div class="pb-2"> | ||
| 6 | + <SearchBar placeholder="搜索" @search="handleSearch" /> | ||
| 7 | + </div> | ||
| 8 | + | ||
| 9 | + <!-- Featured Course Banner --> | ||
| 10 | + <div class="px-4 mb-5"> | ||
| 11 | + <div class="relative rounded-xl overflow-hidden shadow-lg h-40"> | ||
| 12 | + <img | ||
| 13 | + src="https://cdn.ipadbiz.cn/mlaj/images/featured-course.jpg" | ||
| 14 | + alt="传承之道" | ||
| 15 | + class="w-full h-full object-cover" | ||
| 16 | + /> | ||
| 17 | + <div | ||
| 18 | + class="absolute inset-0 bg-gradient-to-b from-transparent to-black/50 flex flex-col justify-end p-4" | ||
| 19 | + > | ||
| 20 | + <h2 class="text-3xl font-bold text-amber-400 drop-shadow-md">传承之道</h2> | ||
| 21 | + <p class="text-xl text-white font-semibold drop-shadow-sm">大理鸡足山游学</p> | ||
| 22 | + </div> | ||
| 23 | + </div> | ||
| 24 | + </div> | ||
| 25 | + | ||
| 26 | + <!-- Today's Live --> | ||
| 27 | + <div class="px-4 mb-4"> | ||
| 28 | + <div class="flex items-center mb-2"> | ||
| 29 | + <h2 class="font-medium">今日直播</h2> | ||
| 30 | + <div | ||
| 31 | + class="ml-2 flex items-center bg-red-100 text-red-700 rounded px-2 py-1 text-xs" | ||
| 32 | + > | ||
| 33 | + <span class="font-medium">{{ hours }}</span> | ||
| 34 | + <span class="mx-1">:</span> | ||
| 35 | + <span class="font-medium">{{ minutes }}</span> | ||
| 36 | + <span class="mx-1">:</span> | ||
| 37 | + <span class="font-medium">00</span> | ||
| 38 | + </div> | ||
| 39 | + </div> | ||
| 40 | + | ||
| 41 | + <!-- Live Stream Cards --> | ||
| 42 | + <div class="grid grid-cols-2 gap-4"> | ||
| 43 | + <LiveStreamCard | ||
| 44 | + v-for="stream in liveStreams" | ||
| 45 | + :key="stream.id" | ||
| 46 | + :stream="stream" | ||
| 47 | + /> | ||
| 48 | + </div> | ||
| 49 | + </div> | ||
| 50 | + | ||
| 51 | + <!-- Value Online Courses --> | ||
| 52 | + <div class="px-4 mb-4"> | ||
| 53 | + <div class="flex justify-between items-center mb-2"> | ||
| 54 | + <h2 class="font-medium">超值线上课</h2> | ||
| 55 | + <router-link to="#" class="text-xs text-gray-500 flex items-center"> | ||
| 56 | + 更多 | ||
| 57 | + <svg | ||
| 58 | + xmlns="http://www.w3.org/2000/svg" | ||
| 59 | + class="h-3 w-3 ml-1" | ||
| 60 | + fill="none" | ||
| 61 | + viewBox="0 0 24 24" | ||
| 62 | + stroke="currentColor" | ||
| 63 | + > | ||
| 64 | + <path | ||
| 65 | + stroke-linecap="round" | ||
| 66 | + stroke-linejoin="round" | ||
| 67 | + stroke-width="2" | ||
| 68 | + d="M9 5l7 7-7 7" | ||
| 69 | + /> | ||
| 70 | + </svg> | ||
| 71 | + </router-link> | ||
| 72 | + </div> | ||
| 73 | + | ||
| 74 | + <!-- Course Cards --> | ||
| 75 | + <div class="space-y-4"> | ||
| 76 | + <CourseCard v-for="course in courses" :key="course.id" :course="course" /> | ||
| 77 | + </div> | ||
| 78 | + </div> | ||
| 79 | + </div> | ||
| 80 | + </AppLayout> | ||
| 81 | +</template> | ||
| 82 | + | ||
| 83 | +<script setup lang="jsx"> | ||
| 84 | +import { computed, defineComponent, h } from "vue"; | ||
| 85 | +import AppLayout from "@/components/layout/AppLayout.vue"; | ||
| 86 | +import SearchBar from "@/components/ui/SearchBar.vue"; | ||
| 87 | +import FrostedGlass from "@/components/ui/FrostedGlass.vue"; | ||
| 88 | +import CourseCard from "@/components/ui/CourseCard.vue"; | ||
| 89 | +import LiveStreamCard from "@/components/ui/LiveStreamCard.vue"; | ||
| 90 | +import { featuredCourse, liveStreams, courses } from "@/utils/mockData"; | ||
| 91 | + | ||
| 92 | +// Search handler | ||
| 93 | +const handleSearch = (query) => { | ||
| 94 | + console.log("Searching for:", query); | ||
| 95 | + // Would implement actual search logic here | ||
| 96 | +}; | ||
| 97 | + | ||
| 98 | +// Current time for the countdown timer | ||
| 99 | +const todayDate = new Date(); | ||
| 100 | +const formattedTime = featuredCourse.liveTime.split(":"); | ||
| 101 | +const hours = computed(() => formattedTime[0]); | ||
| 102 | +const minutes = computed(() => formattedTime[1]); | ||
| 103 | + | ||
| 104 | +// Right content component | ||
| 105 | + | ||
| 106 | +const RightContent = defineComponent({ | ||
| 107 | + setup() { | ||
| 108 | + return () => ( | ||
| 109 | + <button class="p-2"> | ||
| 110 | + <svg | ||
| 111 | + xmlns="http://www.w3.org/2000/svg" | ||
| 112 | + class="h-6 w-6 text-gray-700" | ||
| 113 | + fill="none" | ||
| 114 | + viewBox="0 0 24 24" | ||
| 115 | + stroke="currentColor" | ||
| 116 | + > | ||
| 117 | + <path | ||
| 118 | + stroke-linecap="round" | ||
| 119 | + stroke-linejoin="round" | ||
| 120 | + stroke-width="2" | ||
| 121 | + d="M12 5v.01M12 12v.01M12 19v.01M12 6a1 1 0 110-2 1 1 0 010 2zm0 7a1 1 0 110-2 1 1 0 010 2zm0 7a1 1 0 110-2 1 1 0 010 2z" | ||
| 122 | + /> | ||
| 123 | + </svg> | ||
| 124 | + </button> | ||
| 125 | + ); | ||
| 126 | + }, | ||
| 127 | +}); | ||
| 128 | + | ||
| 129 | +const rightContent = h(RightContent); | ||
| 130 | +</script> |
-
Please register or login to post a comment