refactor(studentPage): 重构学生详情页面布局和样式
- 使用van-config-provider包裹整个页面以支持主题变量 - 调整统计图表stroke-width为70以增强可视性 - 使用van-sticky优化标签页的粘性布局 - 添加返回顶部按钮并设置样式 - 统一调整时间显示字体大小 - 优化状态图标显示效果
Showing
1 changed file
with
123 additions
and
121 deletions
| ... | @@ -2,118 +2,110 @@ | ... | @@ -2,118 +2,110 @@ |
| 2 | * @Author: hookehuyr hookehuyr@gmail.com | 2 | * @Author: hookehuyr hookehuyr@gmail.com |
| 3 | * @Date: 2025-06-19 17:12:19 | 3 | * @Date: 2025-06-19 17:12:19 |
| 4 | * @LastEditors: hookehuyr hookehuyr@gmail.com | 4 | * @LastEditors: hookehuyr hookehuyr@gmail.com |
| 5 | - * @LastEditTime: 2025-06-19 21:32:23 | 5 | + * @LastEditTime: 2025-06-19 22:39:26 |
| 6 | * @FilePath: /mlaj/src/views/teacher/studentPage.vue | 6 | * @FilePath: /mlaj/src/views/teacher/studentPage.vue |
| 7 | * @Description: 学生详情页面 | 7 | * @Description: 学生详情页面 |
| 8 | --> | 8 | --> |
| 9 | <template> | 9 | <template> |
| 10 | - <div class="bg-gradient-to-br from-green-50 via-green-100/30 to-blue-50/30 min-h-screen"> | 10 | + <van-config-provider :theme-vars="themeVars"> |
| 11 | - <!-- 学生基本信息 --> | 11 | + <div class="bg-gradient-to-br from-green-50 via-green-100/30 to-blue-50/30 min-h-screen"> |
| 12 | - <div class="bg-white p-4"> | 12 | + <!-- 学生基本信息 --> |
| 13 | - <div class="flex items-start mb-4"> | 13 | + <div class="bg-white p-4"> |
| 14 | - <van-image round width="4rem" height="4rem" | 14 | + <div class="flex items-start mb-4"> |
| 15 | - :src="studentInfo.avatar || 'https://cdn.ipadbiz.cn/mlaj/images/icon_1.jpeg'" fit="cover" class="mr-4" /> | 15 | + <van-image round width="4rem" height="4rem" |
| 16 | - <div class="flex-1"> | 16 | + :src="studentInfo.avatar || 'https://cdn.ipadbiz.cn/mlaj/images/icon_1.jpeg'" fit="cover" class="mr-4" /> |
| 17 | - <div class="flex items-center mb-2"> | 17 | + <div class="flex-1"> |
| 18 | - <h2 class="text-xl font-bold text-gray-800 mr-2">{{ studentInfo.name }}</h2> | 18 | + <div class="flex items-center mb-2"> |
| 19 | - <van-icon v-if="studentInfo.gender === 'male'" name="friends-o" color="#3b82f6" size="16" /> | 19 | + <h2 class="text-xl font-bold text-gray-800 mr-2">{{ studentInfo.name }}</h2> |
| 20 | - <van-icon v-else name="like-o" color="#ec4899" size="16" /> | 20 | + <van-icon v-if="studentInfo.gender === 'male'" name="friends-o" color="#3b82f6" size="16" /> |
| 21 | - </div> | 21 | + <van-icon v-else name="like-o" color="#ec4899" size="16" /> |
| 22 | - <div class="flex items-center mb-2"> | 22 | + </div> |
| 23 | - <van-icon name="chat-o" size="16" color="#10b981" class="mr-1" /> | 23 | + <div class="flex items-center mb-2"> |
| 24 | - <span class="text-sm text-gray-600 mr-4">{{ studentInfo.className }}</span> | 24 | + <van-icon name="chat-o" size="16" color="#10b981" class="mr-1" /> |
| 25 | - <van-icon name="phone-o" size="16" color="#10b981" class="mr-1" /> | 25 | + <span class="text-sm text-gray-600 mr-4">{{ studentInfo.className }}</span> |
| 26 | - <span class="text-sm text-gray-600">{{ formatPhone(studentInfo.phone) }}</span> | 26 | + <van-icon name="phone-o" size="16" color="#10b981" class="mr-1" /> |
| 27 | - </div> | 27 | + <span class="text-sm text-gray-600">{{ formatPhone(studentInfo.phone) }}</span> |
| 28 | - <!-- 标签 --> | 28 | + </div> |
| 29 | - <div class="flex flex-wrap gap-2"> | 29 | + <!-- 标签 --> |
| 30 | - <van-tag v-for="tag in studentInfo.tags" :key="tag" type="success" size="small"> | 30 | + <div class="flex flex-wrap gap-2"> |
| 31 | - {{ tag }} | 31 | + <van-tag v-for="tag in studentInfo.tags" :key="tag" type="success" size="small"> |
| 32 | - </van-tag> | 32 | + {{ tag }} |
| 33 | + </van-tag> | ||
| 34 | + </div> | ||
| 33 | </div> | 35 | </div> |
| 34 | </div> | 36 | </div> |
| 35 | </div> | 37 | </div> |
| 36 | - </div> | ||
| 37 | 38 | ||
| 38 | - <!-- 所学课程 --> | 39 | + <!-- 所学课程 --> |
| 39 | - <div class="bg-white mt-2 p-4"> | 40 | + <div class="bg-white mt-2 p-4"> |
| 40 | - <div class="flex items-center mb-3"> | 41 | + <div class="flex items-center mb-3"> |
| 41 | - <van-icon name="bookmark-o" size="16" color="#10b981" class="mr-2" /> | 42 | + <van-icon name="bookmark-o" size="16" color="#10b981" class="mr-2" /> |
| 42 | - <span class="text-sm font-medium text-gray-700">所学课程</span> | 43 | + <span class="text-sm font-medium text-gray-700">所学课程</span> |
| 43 | - </div> | 44 | + </div> |
| 44 | - <div class="flex flex-wrap gap-2"> | 45 | + <div class="flex flex-wrap gap-2"> |
| 45 | - <van-tag v-for="course in studentInfo.courses" :key="course" type="primary" size="small"> | 46 | + <van-tag v-for="course in studentInfo.courses" :key="course" type="primary" size="small"> |
| 46 | - {{ course }} | 47 | + {{ course }} |
| 47 | - </van-tag> | 48 | + </van-tag> |
| 49 | + </div> | ||
| 48 | </div> | 50 | </div> |
| 49 | - </div> | ||
| 50 | 51 | ||
| 51 | - <!-- 统计数据 --> | 52 | + <!-- 统计数据 --> |
| 52 | - <div class="mt-2"> | 53 | + <div class="mt-2"> |
| 53 | - <van-row> | 54 | + <van-row> |
| 54 | - <!-- 出勤率 --> | 55 | + <!-- 出勤率 --> |
| 55 | - <van-col span="8"> | 56 | + <van-col span="8"> |
| 56 | - <div class="bg-white p-4 text-center"> | 57 | + <div class="bg-white p-4 text-center"> |
| 57 | - <div class="relative w-16 h-16 mx-auto mb-2"> | 58 | + <div class="relative w-16 h-16 mx-auto mb-2"> |
| 58 | - <van-circle v-model:current-rate="studentStats.attendanceRate" :rate="studentStats.attendanceRate" | 59 | + <van-circle v-model:current-rate="studentStats.attendanceRate" :rate="studentStats.attendanceRate" |
| 59 | - :speed="100" :text="studentStats.attendanceRate + '%'" stroke-width="50" color="#10b981" size="64" /> | 60 | + :speed="100" :text="studentStats.attendanceRate + '%'" stroke-width="70" color="#10b981" size="64" /> |
| 61 | + </div> | ||
| 62 | + <div class="text-sm text-gray-600">出勤率</div> | ||
| 60 | </div> | 63 | </div> |
| 61 | - <div class="text-sm text-gray-600">出勤率</div> | 64 | + </van-col> |
| 62 | - </div> | 65 | + <!-- 作业完成率 --> |
| 63 | - </van-col> | 66 | + <van-col span="8"> |
| 64 | - <!-- 作业完成率 --> | 67 | + <div class="bg-white p-4 text-center"> |
| 65 | - <van-col span="8"> | 68 | + <div class="relative w-16 h-16 mx-auto mb-2"> |
| 66 | - <div class="bg-white p-4 text-center"> | 69 | + <van-circle v-model:current-rate="studentStats.homeworkRate" :rate="studentStats.homeworkRate" |
| 67 | - <div class="relative w-16 h-16 mx-auto mb-2"> | 70 | + :speed="100" :text="studentStats.homeworkRate + '%'" stroke-width="70" color="#3b82f6" size="64" /> |
| 68 | - <van-circle v-model:current-rate="studentStats.homeworkRate" :rate="studentStats.homeworkRate" | 71 | + </div> |
| 69 | - :speed="100" :text="studentStats.homeworkRate + '%'" stroke-width="50" color="#3b82f6" size="64" /> | 72 | + <div class="text-sm text-gray-600">作业完成率</div> |
| 70 | </div> | 73 | </div> |
| 71 | - <div class="text-sm text-gray-600">作业完成率</div> | 74 | + </van-col> |
| 72 | - </div> | 75 | + <!-- 测验成绩 --> |
| 73 | - </van-col> | 76 | + <van-col span="8"> |
| 74 | - <!-- 测验成绩 --> | 77 | + <div class="bg-white p-4 text-center"> |
| 75 | - <van-col span="8"> | 78 | + <div class="relative w-16 h-16 mx-auto mb-2"> |
| 76 | - <div class="bg-white p-4 text-center"> | 79 | + <van-circle v-model:current-rate="studentStats.testScore" :rate="studentStats.testScore" :speed="100" |
| 77 | - <div class="relative w-16 h-16 mx-auto mb-2"> | 80 | + :text="studentStats.testScore + '%'" stroke-width="70" color="#f59e0b" size="64" /> |
| 78 | - <van-circle v-model:current-rate="studentStats.testScore" :rate="studentStats.testScore" :speed="100" | 81 | + </div> |
| 79 | - :text="studentStats.testScore + '%'" stroke-width="50" color="#f59e0b" size="64" /> | 82 | + <div class="text-sm text-gray-600">测验成绩</div> |
| 80 | </div> | 83 | </div> |
| 81 | - <div class="text-sm text-gray-600">测验成绩</div> | 84 | + </van-col> |
| 82 | - </div> | 85 | + </van-row> |
| 83 | - </van-col> | 86 | + </div> |
| 84 | - </van-row> | ||
| 85 | - </div> | ||
| 86 | 87 | ||
| 87 | - <!-- 功能按钮 --> | 88 | + <!-- 功能按钮 --> |
| 88 | - <div class="mt-2 p-4"> | 89 | + <div class="mt-2 p-4"> |
| 89 | - <!-- 状态筛选 --> | 90 | + <!-- 状态筛选 --> |
| 90 | - <div class="flex items-center justify-end mb-4"> | 91 | + <div class="flex items-center justify-end mb-4"> |
| 91 | - <div @click="showStatusPopup = true" class="flex items-center text-sm text-gray-600 cursor-pointer"> | 92 | + <div @click="showStatusPopup = true" class="flex items-center text-sm text-gray-600 cursor-pointer"> |
| 92 | - <span>{{ statusFilter }}</span> | 93 | + <span>{{ statusFilter }}</span> |
| 93 | - <van-icon name="arrow-down" size="14" class="ml-1" /> | 94 | + <van-icon name="arrow-down" size="14" class="ml-1" /> |
| 95 | + </div> | ||
| 94 | </div> | 96 | </div> |
| 95 | </div> | 97 | </div> |
| 96 | - <!-- <div class="flex items-center justify-between mb-3"> | 98 | + |
| 97 | - <div @click="activeTab = 'homework'" | 99 | + <!-- 使用van-sticky包裹van-tabs实现粘性布局 --> |
| 98 | - :class="['flex-1 text-center py-2 text-sm font-medium cursor-pointer', activeTab === 'homework' ? 'text-green-600 border-b-2 border-green-600' : 'text-gray-500']"> | 100 | + <van-sticky :offset-top="0"> |
| 99 | - 作业记录 | 101 | + <div class="bg-white"> |
| 100 | - </div> | 102 | + <van-tabs v-model:active="activeTab" color="#10b981" animated swipeable @change="handleTabChange"> |
| 101 | - <div @click="activeTab = 'evaluation'" | 103 | + <van-tab title="作业记录" name="homework"></van-tab> |
| 102 | - :class="['flex-1 text-center py-2 text-sm font-medium cursor-pointer', activeTab === 'evaluation' ? 'text-green-600 border-b-2 border-green-600' : 'text-gray-500']"> | 104 | + <van-tab title="班主任点评" name="evaluation"></van-tab> |
| 103 | - 班主任点评 | 105 | + <van-tab title="打卡统计" name="statistics"></van-tab> |
| 104 | - </div> | 106 | + </van-tabs> |
| 105 | - <div @click="activeTab = 'statistics'" | ||
| 106 | - :class="['flex-1 text-center py-2 text-sm font-medium cursor-pointer', activeTab === 'statistics' ? 'text-green-600 border-b-2 border-green-600' : 'text-gray-500']"> | ||
| 107 | - 打卡统计 | ||
| 108 | </div> | 107 | </div> |
| 109 | - </div> --> | 108 | + </van-sticky> |
| 110 | - <div class="px-4 py-3 bg-white" style="position: relative;"> | ||
| 111 | - <van-tabs v-model:active="activeTab" color="#10b981" sticky animated swipeable @change="handleTabChange"> | ||
| 112 | - <van-tab title="作业记录" name="homework"></van-tab> | ||
| 113 | - <van-tab title="班主任点评" name="evaluation"></van-tab> | ||
| 114 | - <van-tab title="打卡统计" name="statistics"></van-tab> | ||
| 115 | - </van-tabs> | ||
| 116 | - </div> | ||
| 117 | 109 | ||
| 118 | <!-- 记录列表 --> | 110 | <!-- 记录列表 --> |
| 119 | <van-list v-show="activeTab === 'statistics'" v-model:loading="recordLoading" :finished="recordFinished" | 111 | <van-list v-show="activeTab === 'statistics'" v-model:loading="recordLoading" :finished="recordFinished" |
| ... | @@ -123,12 +115,12 @@ | ... | @@ -123,12 +115,12 @@ |
| 123 | <div class="flex items-center flex-1"> | 115 | <div class="flex items-center flex-1"> |
| 124 | <div class="mr-4"> | 116 | <div class="mr-4"> |
| 125 | <div style="display: flex; justify-content: center;"> | 117 | <div style="display: flex; justify-content: center;"> |
| 126 | - <van-icon name="calendar-o" size="16" color="#6b7280" class="mb-1" /> | 118 | + <van-icon name="calendar-o" size="18" color="#6b7280" class="mb-1" /> |
| 127 | - <span class="text-xs text-gray-500">{{ record.date }}</span> | 119 | + <span class="text-sm text-gray-500">{{ record.date }}</span> |
| 128 | </div> | 120 | </div> |
| 129 | <div style="display: flex; "> | 121 | <div style="display: flex; "> |
| 130 | - <van-icon name="clock-o" size="16" color="#6b7280" class="mb-1" /> | 122 | + <van-icon name="clock-o" size="18" color="#6b7280" class="mb-1" /> |
| 131 | - <span class="text-xs text-gray-500">{{ record.time }}</span> | 123 | + <span class="text-sm text-gray-500">{{ record.time }}</span> |
| 132 | </div> | 124 | </div> |
| 133 | </div> | 125 | </div> |
| 134 | </div> | 126 | </div> |
| ... | @@ -137,7 +129,7 @@ | ... | @@ -137,7 +129,7 @@ |
| 137 | <span v-else-if="record.status === '迟到'" class="text-orange-500 text-sm mr-2">{{ record.status }}</span> | 129 | <span v-else-if="record.status === '迟到'" class="text-orange-500 text-sm mr-2">{{ record.status }}</span> |
| 138 | <span v-else class="text-red-500 text-sm mr-2">{{ record.status }}</span> | 130 | <span v-else class="text-red-500 text-sm mr-2">{{ record.status }}</span> |
| 139 | 131 | ||
| 140 | - <van-icon v-if="record.status === '正常'" name="success" color="#10b981" size="16" /> | 132 | + <van-icon v-if="record.status === '正常'" name="passed" color="#10b981" size="16" /> |
| 141 | <van-icon v-else-if="record.status === '迟到'" name="warning-o" color="#f59e0b" size="16" /> | 133 | <van-icon v-else-if="record.status === '迟到'" name="warning-o" color="#f59e0b" size="16" /> |
| 142 | <van-icon v-else name="close" color="#ef4444" size="16" /> | 134 | <van-icon v-else name="close" color="#ef4444" size="16" /> |
| 143 | </div> | 135 | </div> |
| ... | @@ -214,27 +206,29 @@ | ... | @@ -214,27 +206,29 @@ |
| 214 | </div> | 206 | </div> |
| 215 | </div> | 207 | </div> |
| 216 | </van-list> | 208 | </van-list> |
| 217 | - </div> | 209 | + <van-back-top right="5vw" bottom="10vh" /> |
| 218 | - | 210 | + <div style="height: 5rem;"></div> |
| 219 | - <!-- 状态筛选弹窗 --> | 211 | + |
| 220 | - <van-popup v-model:show="showStatusPopup" position="bottom" round> | 212 | + <!-- 状态筛选弹窗 --> |
| 221 | - <div class="p-4"> | 213 | + <van-popup v-model:show="showStatusPopup" position="bottom" round> |
| 222 | - <div class="text-center text-lg font-bold mb-4">选择状态</div> | 214 | + <div class="p-4"> |
| 223 | - <van-cell-group> | 215 | + <div class="text-center text-lg font-bold mb-4">选择状态</div> |
| 224 | - <van-cell v-for="option in statusOptions" :key="option.value" :title="option.text" clickable | 216 | + <van-cell-group> |
| 225 | - @click="onStatusSelect(option)" :border="false" | 217 | + <van-cell v-for="option in statusOptions" :key="option.value" :title="option.text" clickable |
| 226 | - :class="{ 'text-green-600': statusFilter === option.value }"> | 218 | + @click="onStatusSelect(option)" :border="false" |
| 227 | - <template #right-icon> | 219 | + :class="{ 'text-green-600': statusFilter === option.value }"> |
| 228 | - <van-icon v-if="statusFilter === option.value" name="success" color="#10b981" /> | 220 | + <template #right-icon> |
| 229 | - </template> | 221 | + <van-icon v-if="statusFilter === option.value" name="success" color="#10b981" /> |
| 230 | - </van-cell> | 222 | + </template> |
| 231 | - </van-cell-group> | 223 | + </van-cell> |
| 232 | - <div class="mt-4"> | 224 | + </van-cell-group> |
| 233 | - <van-button block @click="showStatusPopup = false">取消</van-button> | 225 | + <div class="mt-4"> |
| 226 | + <van-button block @click="showStatusPopup = false">取消</van-button> | ||
| 227 | + </div> | ||
| 234 | </div> | 228 | </div> |
| 235 | - </div> | 229 | + </van-popup> |
| 236 | - </van-popup> | 230 | + </div> |
| 237 | - </div> | 231 | + </van-config-provider> |
| 238 | </template> | 232 | </template> |
| 239 | 233 | ||
| 240 | <script setup> | 234 | <script setup> |
| ... | @@ -253,6 +247,10 @@ const router = useRouter() | ... | @@ -253,6 +247,10 @@ const router = useRouter() |
| 253 | const route = useRoute() | 247 | const route = useRoute() |
| 254 | useTitle(route.meta.title); | 248 | useTitle(route.meta.title); |
| 255 | 249 | ||
| 250 | +const themeVars = reactive({ | ||
| 251 | + buttonNormalFontSize: '1rem', | ||
| 252 | +}) | ||
| 253 | + | ||
| 256 | // 学生信息 | 254 | // 学生信息 |
| 257 | const studentInfo = ref({ | 255 | const studentInfo = ref({ |
| 258 | id: 1, | 256 | id: 1, |
| ... | @@ -685,7 +683,11 @@ const formatData = (data) => { | ... | @@ -685,7 +683,11 @@ const formatData = (data) => { |
| 685 | } | 683 | } |
| 686 | </script> | 684 | </script> |
| 687 | 685 | ||
| 688 | -<style scoped lang="less"> | 686 | +<style lang="less"> |
| 687 | +.van-back-top { | ||
| 688 | + background-color: #4caf50; | ||
| 689 | +} | ||
| 690 | + | ||
| 689 | /* 自定义样式 */ | 691 | /* 自定义样式 */ |
| 690 | .van-circle { | 692 | .van-circle { |
| 691 | font-size: 12px; | 693 | font-size: 12px; | ... | ... |
-
Please register or login to post a comment