refactor(StudyPage, CourseList): 优化布局和样式,提升用户体验
- 在StudyPage.vue中,将学习统计部分的布局从列表形式改为网格形式,使其更直观 - 在CourseList.vue中,重新设计课程列表的布局,增加缩略图样式和进度条显示,提升可读性
Showing
2 changed files
with
62 additions
and
39 deletions
| ... | @@ -6,18 +6,29 @@ | ... | @@ -6,18 +6,29 @@ |
| 6 | <div class="course-list"> | 6 | <div class="course-list"> |
| 7 | <van-list v-model:loading="loading" :finished="finished" finished-text="没有更多了" @load="onLoad"> | 7 | <van-list v-model:loading="loading" :finished="finished" finished-text="没有更多了" @load="onLoad"> |
| 8 | <div v-for="course in courses" :key="course.id" | 8 | <div v-for="course in courses" :key="course.id" |
| 9 | - class="course-item bg-white mb-3 rounded-lg overflow-hidden"> | 9 | + class="course-item bg-white p-3 rounded-lg overflow-hidden flex"> |
| 10 | - <van-cell :title="course.title" :label="course.type" class="pb-2"> | 10 | + <div class="relative w-[120px] h-full flex-shrink-0"> |
| 11 | - <template #icon> | 11 | + <van-image :src="course.thumbnail" width="120" height="100%" fit="cover" class="item-cover"> |
| 12 | - <van-image :src="course.thumbnail" width="120" height="68" fit="cover" class="mr-3 rounded" /> | 12 | + <div class="absolute bg-white/80 px-2 py-0.5 text-xs rounded" |
| 13 | - </template> | 13 | + style="right: 0.25rem; bottom: 0.5rem"> |
| 14 | - </van-cell> | 14 | + {{ course.type }} |
| 15 | - <div class="px-4 pb-4"> | 15 | + </div> |
| 16 | - <div class="flex justify-between items-center text-sm text-gray-600 mb-2"> | 16 | + </van-image> |
| 17 | - <span>已学习 {{ formatDuration(course.studyTime) }}</span> | 17 | + </div> |
| 18 | - <span>{{ course.progress }}%</span> | 18 | + <div class="flex-1 p-3 flex flex-col" style="padding-top: 0; padding-right: 0"> |
| 19 | + <div class="text-sm font-medium mb-2 mt-0">{{ course.title }}</div> | ||
| 20 | + <div class="mt-auto"> | ||
| 21 | + <div class="flex items-center w-full"> | ||
| 22 | + <span class="text-sm text-gray-400 shrink-0" style="font-size: 0.75rem; width: 5rem">已学习 {{ | ||
| 23 | + formatDuration(course.studyTime) }}</span> | ||
| 24 | + <div class="flex-1 mx-4"> | ||
| 25 | + <van-progress :percentage="course.progress" :stroke-width="4" color="#4080ff" | ||
| 26 | + :show-pivot="false" /> | ||
| 27 | + </div> | ||
| 28 | + <span class="text-sm text-gray-400 shrink-0 text-center" | ||
| 29 | + style="font-size: 0.75rem; width: 2rem; text-align: right">{{ course.progress }}%</span> | ||
| 30 | + </div> | ||
| 19 | </div> | 31 | </div> |
| 20 | - <van-progress :percentage="course.progress" :stroke-width="4" color="#4080ff" /> | ||
| 21 | </div> | 32 | </div> |
| 22 | </div> | 33 | </div> |
| 23 | </van-list> | 34 | </van-list> |
| ... | @@ -25,42 +36,46 @@ | ... | @@ -25,42 +36,46 @@ |
| 25 | </template> | 36 | </template> |
| 26 | 37 | ||
| 27 | <script setup> | 38 | <script setup> |
| 28 | -import { ref } from 'vue' | 39 | +import { ref } from "vue"; |
| 29 | 40 | ||
| 30 | // 接收课程列表数据 | 41 | // 接收课程列表数据 |
| 31 | const props = defineProps({ | 42 | const props = defineProps({ |
| 32 | courses: { | 43 | courses: { |
| 33 | type: Array, | 44 | type: Array, |
| 34 | - default: () => [] | 45 | + default: () => [], |
| 35 | - } | 46 | + }, |
| 36 | -}) | 47 | +}); |
| 37 | 48 | ||
| 38 | // 列表加载状态 | 49 | // 列表加载状态 |
| 39 | -const loading = ref(false) | 50 | +const loading = ref(false); |
| 40 | -const finished = ref(true) // 由于使用的是传入的静态数据,所以直接设置为完成状态 | 51 | +const finished = ref(true); // 由于使用的是传入的静态数据,所以直接设置为完成状态 |
| 41 | 52 | ||
| 42 | // 加载更多 | 53 | // 加载更多 |
| 43 | const onLoad = () => { | 54 | const onLoad = () => { |
| 44 | - loading.value = false | 55 | + loading.value = false; |
| 45 | -} | 56 | +}; |
| 46 | 57 | ||
| 47 | // 格式化时长显示 | 58 | // 格式化时长显示 |
| 48 | const formatDuration = (seconds) => { | 59 | const formatDuration = (seconds) => { |
| 49 | - const hours = Math.floor(seconds / 3600) | 60 | + const hours = Math.floor(seconds / 3600); |
| 50 | - const minutes = Math.floor((seconds % 3600) / 60) | 61 | + const minutes = Math.floor((seconds % 3600) / 60); |
| 51 | if (hours > 0) { | 62 | if (hours > 0) { |
| 52 | - return `${hours}小时${minutes}分钟` | 63 | + return `${hours}小时${minutes}分钟`; |
| 53 | } | 64 | } |
| 54 | - return `${minutes}分钟` | 65 | + return `${minutes}分钟`; |
| 55 | -} | 66 | +}; |
| 56 | </script> | 67 | </script> |
| 57 | 68 | ||
| 58 | <style scoped> | 69 | <style scoped> |
| 59 | .course-list { | 70 | .course-list { |
| 60 | - padding: 0.5rem; | 71 | + padding: 0rem; |
| 61 | } | 72 | } |
| 62 | 73 | ||
| 63 | .course-item { | 74 | .course-item { |
| 64 | box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05); | 75 | box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05); |
| 65 | } | 76 | } |
| 77 | + | ||
| 78 | +:deep(.van-image__img) { | ||
| 79 | + border-radius: 0.5rem; | ||
| 80 | +} | ||
| 66 | </style> | 81 | </style> | ... | ... |
| ... | @@ -31,18 +31,14 @@ | ... | @@ -31,18 +31,14 @@ |
| 31 | <van-tab title="学习记录" name="record"> | 31 | <van-tab title="学习记录" name="record"> |
| 32 | <div class="p-4"> | 32 | <div class="p-4"> |
| 33 | <div class="flex space-x-4 mb-4"> | 33 | <div class="flex space-x-4 mb-4"> |
| 34 | - <button | 34 | + <button class="rounded-full px-6 py-2 text-sm transition-colors" |
| 35 | - class="rounded-full px-6 py-2 text-sm transition-colors" | ||
| 36 | :class="courseType === 'column' ? 'bg-green-500 text-white' : 'bg-gray-100 text-gray-600'" | 35 | :class="courseType === 'column' ? 'bg-green-500 text-white' : 'bg-gray-100 text-gray-600'" |
| 37 | - @click="courseType = 'column'" | 36 | + @click="courseType = 'column'"> |
| 38 | - > | ||
| 39 | 专栏 | 37 | 专栏 |
| 40 | </button> | 38 | </button> |
| 41 | - <button | 39 | + <button class="rounded-full px-6 py-2 text-sm transition-colors" |
| 42 | - class="rounded-full px-6 py-2 text-sm transition-colors" | ||
| 43 | :class="courseType === 'single' ? 'bg-green-500 text-white' : 'bg-gray-100 text-gray-600'" | 40 | :class="courseType === 'single' ? 'bg-green-500 text-white' : 'bg-gray-100 text-gray-600'" |
| 44 | - @click="courseType = 'single'" | 41 | + @click="courseType = 'single'"> |
| 45 | - > | ||
| 46 | 单课 | 42 | 单课 |
| 47 | </button> | 43 | </button> |
| 48 | </div> | 44 | </div> |
| ... | @@ -54,12 +50,24 @@ | ... | @@ -54,12 +50,24 @@ |
| 54 | <!-- 学习统计标签 --> | 50 | <!-- 学习统计标签 --> |
| 55 | <van-tab title="学习统计" name="stats"> | 51 | <van-tab title="学习统计" name="stats"> |
| 56 | <div class="p-4"> | 52 | <div class="p-4"> |
| 57 | - <van-cell-group inset> | 53 | + <div class="grid grid-cols-2 gap-4"> |
| 58 | - <van-cell title="总学习时长" :value="formatDuration(stats.totalDuration)" /> | 54 | + <div class="bg-white rounded-lg p-4 shadow-sm"> |
| 59 | - <van-cell title="已完成课程" :value="`${stats.completedCourses}门`" /> | 55 | + <div class="text-gray-500 text-sm mb-1">总学习时长</div> |
| 60 | - <van-cell title="学习天数" :value="`${stats.studyDays}天`" /> | 56 | + <div class="text-black font-medium">{{ formatDuration(stats.totalDuration) }}</div> |
| 61 | - <van-cell title="平均每日学习" :value="formatDuration(stats.avgDailyDuration)" /> | 57 | + </div> |
| 62 | - </van-cell-group> | 58 | + <div class="bg-white rounded-lg p-4 shadow-sm"> |
| 59 | + <div class="text-gray-500 text-sm mb-1">已完成课程</div> | ||
| 60 | + <div class="text-black font-medium">{{ stats.completedCourses }}门</div> | ||
| 61 | + </div> | ||
| 62 | + <div class="bg-white rounded-lg p-4 shadow-sm"> | ||
| 63 | + <div class="text-gray-500 text-sm mb-1">学习天数</div> | ||
| 64 | + <div class="text-black font-medium">{{ stats.studyDays }}天</div> | ||
| 65 | + </div> | ||
| 66 | + <div class="bg-white rounded-lg p-4 shadow-sm"> | ||
| 67 | + <div class="text-gray-500 text-sm mb-1">平均每日学习</div> | ||
| 68 | + <div class="text-black font-medium">{{ formatDuration(stats.avgDailyDuration) }}</div> | ||
| 69 | + </div> | ||
| 70 | + </div> | ||
| 63 | </div> | 71 | </div> |
| 64 | </van-tab> | 72 | </van-tab> |
| 65 | </van-tabs> | 73 | </van-tabs> | ... | ... |
-
Please register or login to post a comment