hookehuyr

refactor(router): 重构路由配置并删除无用文件

重构了路由配置文件,更新了路由路径和组件名称,并添加了元数据。删除了不再使用的About.vue文件,同时新增了CoursesPage.vue页面。
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
......
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>
......
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>
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>