Toggle navigation
Toggle navigation
This project
Loading...
Sign in
Hooke
/
mlaj
Go to a project
Toggle navigation
Toggle navigation pinning
Projects
Groups
Snippets
Help
Project
Activity
Repository
Pipelines
Graphs
Issues
0
Merge Requests
0
Wiki
Snippets
Network
Create a new issue
Builds
Commits
Issue Boards
Authored by
hookehuyr
2025-06-20 00:13:02 +0800
Browse Files
Options
Browse Files
Download
Email Patches
Plain Diff
Commit
b14baa3970aac32e352e5b9266377ad7e8345a74
b14baa39
1 parent
a5ac66c9
feat(teacher): 添加课程选择和样式优化
- 在学生页面添加课程单选功能 - 优化班级页面样式和交互细节 - 增加主题配置和搜索框样式调整
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
199 additions
and
122 deletions
src/views/teacher/myClassPage.vue
src/views/teacher/studentPage.vue
src/views/teacher/myClassPage.vue
View file @
b14baa3
...
...
@@ -2,157 +2,169 @@
* @Author: hookehuyr hookehuyr@gmail.com
* @Date: 2025-01-20 10:00:00
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2025-06-
19 16:46:0
6
* @LastEditTime: 2025-06-
20 00:09:4
6
* @FilePath: /mlaj/src/views/teacher/myClassPage.vue
* @Description: 我的班级页面
-->
<template>
<div class="bg-gradient-to-br from-green-50 via-green-100/30 to-blue-50/30 min-h-screen">
<!-- 用户信息卡片 -->
<div>
<div class="bg-white p-4">
<div class="flex items-center mb-4">
<van-image round width="3rem" height="3rem"
:src="userInfo.avatar || 'https://cdn.ipadbiz.cn/mlaj/images/icon_1.jpeg'" fit="cover" class="mr-3" />
<div class="flex-1">
<h2 class="text-lg font-bold text-gray-800">{{ userInfo.name }}</h2>
<div class="flex items-center mt-1">
<van-icon name="clock-o" size="20" color="#10b981" class="mr-1" />
<van-icon name="chat-o" size="20" color="#10b981" class="mr-1" />
<van-icon name="comment-circle-o" size="20" color="#10b981" />
<van-config-provider :theme-vars="themeVars">
<div class="bg-gradient-to-br from-green-50 via-green-100/30 to-blue-50/30 min-h-screen">
<!-- 用户信息卡片 -->
<div>
<div class="bg-white p-4">
<div class="flex items-center mb-4">
<van-image round width="3rem" height="3rem"
:src="userInfo.avatar || 'https://cdn.ipadbiz.cn/mlaj/images/icon_1.jpeg'" fit="cover" class="mr-3" />
<div class="flex-1">
<h2 class="text-lg font-bold text-gray-800">{{ userInfo.name }}</h2>
<div class="flex items-center mt-1">
<van-icon name="clock-o" size="20" color="#10b981" class="mr-1" />
<van-icon name="chat-o" size="20" color="#10b981" class="mr-1" />
<van-icon name="comment-circle-o" size="20" color="#10b981" />
</div>
</div>
</div>
</div>
</div>
</div>
<!-- 筛选器 -->
<div>
<van-sticky>
<van-dropdown-menu active-color="#10b981">
<van-dropdown-item v-model="gradeFilter" :options="gradeOptions" @change="handleGradeChange" />
<van-dropdown-item v-model="classFilter" :options="classOptions" @change="handleClassChange" />
<van-dropdown-item v-model="courseFilter" :options="courseOptions" @change="handleCourseChange" />
</van-dropdown-menu>
</van-sticky>
</div>
<!-- 筛选器 -->
<div>
<van-sticky>
<van-dropdown-menu active-color="#10b981">
<van-dropdown-item v-model="gradeFilter" :options="gradeOptions" @change="handleGradeChange" />
<van-dropdown-item v-model="classFilter" :options="classOptions" @change="handleClassChange" />
<van-dropdown-item v-model="courseFilter" :options="courseOptions" @change="handleCourseChange" />
</van-dropdown-menu>
</van-sticky>
</div>
<!-- 统计数据 -->
<div>
<van-row>
<!-- 出勤率 -->
<van-col span="8">
<div class="bg-white p-4 text-center">
<div class="relative w-16 h-16 mx-auto mb-2">
<van-circle v-model:current-rate="attendanceRate" :rate="attendanceRate" :speed="100"
:text="attendanceRate + '%'" stroke-width="50" color="#10b981" size="64" />
<div style="height: 0.5rem;"></div>
<!-- 统计数据 -->
<div>
<van-row>
<!-- 出勤率 -->
<van-col span="8">
<div class="bg-white p-4 text-center">
<div class="relative w-16 h-16 mx-auto mb-2">
<van-circle v-model:current-rate="attendanceRate" :rate="attendanceRate" :speed="100"
:text="attendanceRate + '%'" stroke-width="70" color="#10b981" size="64" />
</div>
<div class="text-sm text-gray-600">出勤率</div>
</div>
<div class="text-sm text-gray-600">出勤率</div
>
<
/div
>
</van-col
>
<!-- 任务完成 --
>
<van-col span="8
">
<div class="bg-white p-4 text-center">
<div class="relative w-16 h-16 mx-auto mb-2"
>
<
van-circle v-model:current-rate="taskCompletionRate" :rate="taskCompletionRate" :speed="100"
:text="taskCompletionRate + '%'" stroke-width="50" color="#3b82f6" size="64" /
>
</van-col
>
<
!-- 任务完成 --
>
<van-col span="8"
>
<div class="bg-white p-4 text-center"
>
<div class="relative w-16 h-16 mx-auto mb-2
">
<van-circle v-model:current-rate="taskCompletionRate" :rate="taskCompletionRate" :speed="100"
:text="taskCompletionRate + '%'" stroke-width="70" color="#3b82f6" size="64" /
>
<
/div>
<div class="text-sm text-gray-600">任务完成</div
>
</div>
<div class="text-sm text-gray-600">任务完成</div
>
<
/div
>
</van-col
>
<!-- 学习进度 --
>
<van-col span="8
">
<div class="bg-white p-4 text-center">
<div class="relative w-16 h-16 mx-auto mb-2"
>
<
van-circle v-model:current-rate="learningProgress" :rate="learningProgress" :speed="100"
:text="learningProgress + '%'" stroke-width="50" color="#f59e0b" size="64" /
>
</van-col
>
<
!-- 学习进度 --
>
<van-col span="8"
>
<div class="bg-white p-4 text-center"
>
<div class="relative w-16 h-16 mx-auto mb-2
">
<van-circle v-model:current-rate="learningProgress" :rate="learningProgress" :speed="100"
:text="learningProgress + '%'" stroke-width="70" color="#f59e0b" size="64" /
>
<
/div>
<div class="text-sm text-gray-600">学习进度</div
>
</div>
<div class="text-sm text-gray-600">学习进度</div>
</div>
</van-col>
</van-row>
</div>
</van-col>
</van-row>
</div>
<!-- 班级成员 -->
<div class="">
<!-- 班级成员 -->
<div class="">
<!-- 标题和搜索 -->
<div class="p-4 border-b border-gray-100 bg-white">
<div class="flex items-center justify-between mb-3">
<h3 class="text-lg font-bold text-gray-800">班级成员 ({{ studentList.length }})</h3>
<div @click="showSortPopup = true" class="flex items-center text-sm text-gray-600 cursor-pointer">
<span>{{ sortFilter }}</span>
<van-icon name="arrow-down" size="14" class="ml-1" />
<div class="">
<!-- 标题和搜索 -->
<div class="p-4 border-b border-gray-100 bg-white">
<div class="flex items-center justify-between mb-3">
<h3 class="text-lg font-bold text-gray-800">班级成员 ({{ studentList.length }})</h3>
<div @click="showSortPopup = true" class="flex items-center text-sm text-gray-600 cursor-pointer">
<span>{{ sortFilter }}</span>
<van-icon name="arrow-down" size="14" class="ml-1" />
</div>
</div>
<van-search v-model="searchKeyword" placeholder="请搜索" shape="round" @search="handleSearch" @input="handleSearch" />
</div>
<van-search v-model="searchKeyword" placeholder="请搜索" @search="handleSearch" @input="handleSearch" />
</div>
<!-- 学生列表 -->
<div class="p-4">
<van-list v-model:loading="loading" :finished="finished" finished-text="没有更多了" @load="onLoad">
<div v-for="student in filteredStudentList" :key="student.id"
class="flex items-center justify-between py-3 border-gray-50 bg-white rounded-xl p-4 text-center shadow-sm mb-4"
@click="handleStudentClick(student)">
<div class="flex items-center flex-1">
<van-image round width="2.5rem" height="2.5rem"
:src="student.avatar || 'https://cdn.ipadbiz.cn/mlaj/images/icon_1.jpeg'" fit="cover" class="mr-3" />
<div class="flex-1">
<div class="flex items-center">
<span class="font-medium text-gray-800 mr-2">{{ student.name }}</span>
<van-icon v-if="student.gender === 'male'" name="friends-o" color="#3b82f6" size="14" />
<van-icon v-else name="like-o" color="#ec4899" size="14" />
<!-- 学生列表 -->
<div class="p-4">
<van-list v-model:loading="loading" :finished="finished" finished-text="没有更多了" @load="onLoad">
<div v-for="student in filteredStudentList" :key="student.id"
class="flex items-center justify-between py-3 border-gray-50 bg-white rounded-xl p-4 text-center shadow-sm mb-4"
@click="handleStudentClick(student)">
<div class="flex items-center flex-1">
<van-image round width="2.5rem" height="2.5rem"
:src="student.avatar || 'https://cdn.ipadbiz.cn/mlaj/images/icon_1.jpeg'" fit="cover" class="mr-3" />
<div class="flex-1">
<div class="flex items-center">
<span class="font-medium text-gray-800 mr-2">{{ student.name }}</span>
<van-icon v-if="student.gender === 'male'" name="friends-o" color="#3b82f6" size="14" />
<van-icon v-else name="like-o" color="#ec4899" size="14" />
</div>
<div class="text-sm text-gray-500" style="text-align: left;">{{ student.className }}</div>
</div>
<div class="text-sm text-gray-500" style="text-align: left;">{{ student.className }}</div>
</div>
</div>
<div class="text-right">
<div class="flex items-center text-sm text-gray-500 mb-1">
<van-icon name="phone-o" size="12" class="mr-1" />
<span>{{ formatPhone(student.phone) }}</span>
<div class="text-right">
<div class="flex items-center text-sm text-gray-500 mb-1">
<van-icon name="phone-o" size="12" class="mr-1" />
<span>{{ formatPhone(student.phone) }}</span>
</div>
<div class="text-xs text-gray-400">{{ student.lastActiveTime }}</div>
</div>
<
div class="text-xs text-gray-400">{{ student.lastActiveTime }}</div
>
<
van-icon name="arrow" color="#d1d5db" size="16" class="ml-2" /
>
</div>
<van-icon name="arrow" color="#d1d5db" size="16" class="ml-2" />
</div>
</van-list>
</van-list>
</div>
</div>
</div>
</div>
<!-- 排序弹窗 -->
<van-popup v-model:show="showSortPopup" position="bottom" round>
<div class="p-4">
<div class="text-center text-lg font-bold mb-4">选择排序方式</div>
<van-cell-group>
<van-cell
v-for="option in sortOptions"
:key="option.value"
:title="option.text"
clickable
@click="onSortSelect(option)"
:border="false"
:class="{ 'text-green-600': sortFilter === option.value }"
>
<template #right-icon>
<van-icon v-if="sortFilter === option.value" name="success" color="#10b981" />
</template>
</van-cell>
</van-cell-group>
<div class="mt-4">
<van-button block @click="showSortPopup = false">取消</van-button>
<!-- 排序弹窗 -->
<van-popup v-model:show="showSortPopup" position="bottom" round>
<div class="p-4">
<div class="text-center text-lg font-bold mb-4">选择排序方式</div>
<van-cell-group>
<van-cell
v-for="option in sortOptions"
:key="option.value"
:title="option.text"
clickable
@click="onSortSelect(option)"
:border="false"
:class="{ 'text-green-600': sortFilter === option.value }"
>
<template #right-icon>
<van-icon v-if="sortFilter === option.value" name="success" color="#10b981" />
</template>
</van-cell>
</van-cell-group>
<div class="mt-4">
<van-button block @click="showSortPopup = false">取消</van-button>
</div>
</div>
</
div
>
</
van-popup
>
</
div
>
</
van-popup
>
</
div
>
</
van-config-provider
>
</template>
<script setup>
import { ref, computed, onMounted } from 'vue'
import { useRouter } from 'vue-router'
import AppLayout from '@/layouts/AppLayout.vue'
import { useTitle } from '@vueuse/core';
const router = useRouter()
const route = useRoute()
useTitle(route.meta.title);
const themeVars = ref({
'dropdownMenuShadow': '#fff',
searchInputHeight: '2.5rem',
})
// 用户信息
const userInfo = ref({
...
...
@@ -238,6 +250,42 @@ const studentList = ref([
phone: '13643214321',
lastActiveTime: '30分钟前活跃',
avatar: 'https://cdn.ipadbiz.cn/mlaj/images/icon_1.jpeg'
},
{
id: 1,
name: '张明',
gender: 'male',
className: '高一(3)班',
phone: '13812345678',
lastActiveTime: '5分钟前活跃',
avatar: 'https://cdn.ipadbiz.cn/mlaj/images/icon_1.jpeg'
},
{
id: 2,
name: '李华',
gender: 'female',
className: '高一(3)班',
phone: '13987654321',
lastActiveTime: '10分钟前活跃',
avatar: 'https://cdn.ipadbiz.cn/mlaj/images/icon_1.jpeg'
},
{
id: 3,
name: '王强',
gender: 'male',
className: '高一(2)班',
phone: '13512349876',
lastActiveTime: '15分钟前活跃',
avatar: 'https://cdn.ipadbiz.cn/mlaj/images/icon_1.jpeg'
},
{
id: 4,
name: '赵敏',
gender: 'female',
className: '高一(1)班',
phone: '13643214321',
lastActiveTime: '30分钟前活跃',
avatar: 'https://cdn.ipadbiz.cn/mlaj/images/icon_1.jpeg'
}
])
...
...
@@ -360,7 +408,7 @@ onMounted(() => {
})
</script>
<style
scoped
>
<style
lang="less"
>
/* 自定义样式 */
.van-dropdown-menu {
background-color: white;
...
...
@@ -374,8 +422,8 @@ onMounted(() => {
}
.van-search {
background-color: #f9fafb;
border-radius: 0.5rem;
//
background-color: #f9fafb;
//
border-radius: 0.5rem;
}
.van-list {
...
...
src/views/teacher/studentPage.vue
View file @
b14baa3
...
...
@@ -2,7 +2,7 @@
* @Author: hookehuyr hookehuyr@gmail.com
* @Date: 2025-06-19 17:12:19
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2025-06-
19 23:27:5
7
* @LastEditTime: 2025-06-
20 00:11:3
7
* @FilePath: /mlaj/src/views/teacher/studentPage.vue
* @Description: 学生详情页面
-->
...
...
@@ -43,7 +43,16 @@
<span class="text-sm font-medium text-gray-700">所学课程</span>
</div>
<div class="flex flex-wrap gap-2">
<van-tag v-for="course in studentInfo.courses" :key="course" type="primary" size="large">
<van-tag
v-for="course in studentInfo.courses"
:key="course"
:type="selectedCourses.includes(course) ? 'primary' : 'default'"
:color="selectedCourses.includes(course) ? '#10b981' : '#f0f0f0'"
:text-color="selectedCourses.includes(course) ? '#ffffff' : '#666666'"
size="large"
@click="toggleCourseSelection(course)"
class="cursor-pointer transition-all duration-200 hover:opacity-80"
>
{{ course }}
</van-tag>
</div>
...
...
@@ -263,6 +272,9 @@ const studentInfo = ref({
courses: ['讲师训2025', '亲子学堂课程']
})
// 选中的课程列表(默认选中第一个课程)
const selectedCourses = ref([studentInfo.value.courses[0] || ''])
// 统计数据
const studentStats = ref({
attendanceRate: 92,
...
...
@@ -277,6 +289,23 @@ const activeTab = ref('homework')
const statusFilter = ref('按状态')
const showStatusPopup = ref(false)
/**
* 切换课程选中状态(单选模式)
* @param {string} course - 课程名称
*/
const toggleCourseSelection = (course) => {
if (selectedCourses.value.includes(course)) {
// 如果已选中,则取消选中
selectedCourses.value = []
} else {
// 如果未选中,则设置为当前选中的课程(单选)
selectedCourses.value = [course]
}
// 可以在这里添加其他业务逻辑,比如筛选相关数据
console.log('当前选中的课程:', selectedCourses.value)
}
// 状态选项
const statusOptions = ref([
{ text: '按状态', value: '按状态' },
...
...
Please
register
or
login
to post a comment