智慧教务系统
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

592 lines
13 KiB

<!--家长端用户信息管理页面-->
<template>
<view class="main_box">
<view class="navbar_section">
<view class="title">用户信息</view>
</view>
<!-- 家长信息展示 -->
<view class="parent_info_section">
<view class="parent_name">{{ parentInfo.name || '张家长' }}</view>
<view class="parent_phone">{{ parentInfo.phone_number || '13800138000' }}</view>
</view>
<!-- 选中孩子信息弹窗 -->
<view class="child_popup" v-if="showChildPopup" @click="closeChildPopup">
<view class="popup_content" @click.stop>
<view class="popup_header">
<view class="popup_title">选择孩子</view>
<view class="popup_close" @click="closeChildPopup">×</view>
</view>
<view class="popup_children_list">
<view
v-for="child in childrenList"
:key="child.id"
:class="['popup_child_item', selectedChild && selectedChild.id === child.id ? 'selected' : '']"
@click="selectChildFromPopup(child)"
>
<view class="popup_child_info">
<view class="popup_child_name">{{ child.name }}</view>
<view class="popup_child_details">
<text class="popup_detail_tag">{{ child.gender === 1 ? '男' : '女' }}</text>
<text class="popup_detail_tag">{{ Math.floor(child.age) }}岁</text>
</view>
<view class="popup_child_campus">{{ child.campus_name || '未分配' }}</view>
<view class="popup_child_class">{{ child.class_name || '未分配' }}</view>
</view>
<view class="popup_child_courses">{{ child.remaining_courses || 0 }}课时</view>
</view>
</view>
</view>
</view>
<!-- 当前选中孩子的统计信息 -->
<view class="selected_child_section" v-if="selectedChild">
<view class="selected_child_header">
<view class="selected_child_info">
<view class="selected_child_name">{{ selectedChild.name }}</view>
<view class="selected_child_details">
<text class="selected_detail_tag">{{ selectedChild.gender === 1 ? '男' : '女' }}</text>
<text class="selected_detail_tag">{{ Math.floor(selectedChild.age) }}岁</text>
<text class="selected_detail_tag">{{ selectedChild.campus_name || '未分配校区' }}</text>
</view>
</view>
<view class="switch_button" @click="openChildPopup">切换</view>
</view>
<view class="stats_grid">
<view class="stat_item">
<view class="stat_number">{{ selectedChild.total_courses || 0 }}</view>
<view class="stat_label">总课程</view>
</view>
<view class="stat_item">
<view class="stat_number">{{ selectedChild.completed_courses || 0 }}</view>
<view class="stat_label">已完成</view>
</view>
<view class="stat_item">
<view class="stat_number">{{ selectedChild.remaining_courses || 0 }}</view>
<view class="stat_label">剩余课时</view>
</view>
<view class="stat_item">
<view class="stat_number">{{ selectedChild.attendance_rate || 0 }}%</view>
<view class="stat_label">出勤率</view>
</view>
</view>
</view>
<!-- 功能菜单 - 九宫格样式 -->
<view class="main_section">
<view class="grid_container">
<view class="grid_item" @click="viewChildDetail">
<view class="grid_icon">
<image src="/static/icon-img/tou.png" class="icon_image"></image>
</view>
<view class="grid_text">孩子详情</view>
</view>
<view class="grid_item" @click="viewCourses">
<view class="grid_icon">
<image src="/static/icon-img/kkry.png" class="icon_image"></image>
</view>
<view class="grid_text">课程管理</view>
</view>
<view class="grid_item" @click="viewMaterials">
<view class="grid_icon">
<image src="/static/icon-img/liu.png" class="icon_image"></image>
</view>
<view class="grid_text">教学资料</view>
</view>
<view class="grid_item" @click="viewServices">
<view class="grid_icon">
<image src="/static/icon-img/notice.png" class="icon_image"></image>
</view>
<view class="grid_text">服务管理</view>
</view>
<view class="grid_item" @click="viewOrders">
<view class="grid_icon">
<image src="/static/icon-img/used.png" class="icon_image"></image>
</view>
<view class="grid_text">订单管理</view>
</view>
<view class="grid_item" @click="viewMessages">
<view class="grid_icon">
<image src="/static/icon-img/notice.png" class="icon_image"></image>
</view>
<view class="grid_text">消息管理</view>
</view>
<view class="grid_item" @click="viewContracts">
<view class="grid_icon">
<image src="/static/icon-img/warn.png" class="icon_image"></image>
</view>
<view class="grid_text">合同管理</view>
</view>
<!-- 空白占位,保持九宫格对齐 -->
<view class="grid_item empty_item"></view>
<view class="grid_item empty_item"></view>
</view>
</view>
</view>
</template>
<script>
import { mapState, mapMutations } from 'vuex'
import apiRoute from '@/api/apiRoute.js'
export default {
data() {
return {
parentInfo: {},
childrenList: [],
showChildPopup: false,
loading: false
}
},
computed: {
...mapState(['selectedChild'])
},
onLoad() {
// 设置用户角色为家长
this.setUserRole('parent')
this.loadChildrenList()
console.log('用户信息页面加载完成')
},
onShow() {
// 页面显示时刷新数据
console.log('用户信息页面显示')
},
methods: {
...mapMutations(['SET_USER_ROLE', 'SET_SELECTED_CHILD', 'SET_CHILDREN_LIST']),
setUserRole(role) {
this.SET_USER_ROLE(role)
},
async loadChildrenList() {
this.loading = true
try {
console.log('开始加载孩子列表...')
const response = await apiRoute.parent_getChildrenList()
console.log('孩子列表响应:', response)
if (response.code === 1) {
this.childrenList = response.data.data || []
this.parentInfo = response.data.parent_info || {}
this.SET_CHILDREN_LIST(this.childrenList)
console.log('加载到的孩子列表:', this.childrenList)
console.log('家长信息:', this.parentInfo)
// 如果没有选中的孩子且有孩子列表,默认选中第一个
if (!this.selectedChild && this.childrenList.length > 0) {
this.SET_SELECTED_CHILD(this.childrenList[0])
}
} else {
console.error('获取孩子列表失败:', response)
uni.showToast({
title: response.msg || '获取孩子列表失败',
icon: 'none'
})
}
} catch (error) {
console.error('获取孩子列表失败:', error)
uni.showToast({
title: '获取孩子列表失败',
icon: 'none'
})
} finally {
this.loading = false
}
},
openChildPopup() {
this.showChildPopup = true
},
closeChildPopup() {
this.showChildPopup = false
},
selectChildFromPopup(child) {
this.SET_SELECTED_CHILD(child)
console.log('选中孩子:', child)
this.closeChildPopup()
},
viewChildDetail() {
if (!this.selectedChild) {
uni.showToast({
title: '请先选择孩子',
icon: 'none'
})
return
}
this.$navigateToPage(`/pages/parent/user-info/child-detail`, {
childId: this.selectedChild.id
})
},
viewCourses() {
if (!this.selectedChild) {
uni.showToast({
title: '请先选择孩子',
icon: 'none'
})
return
}
this.$navigateToPage(`/pages/parent/courses/index`, {
childId: this.selectedChild.id
})
},
viewMaterials() {
if (!this.selectedChild) {
uni.showToast({
title: '请先选择孩子',
icon: 'none'
})
return
}
this.$navigateToPage(`/pages/parent/materials/index`, {
childId: this.selectedChild.id
})
},
viewServices() {
if (!this.selectedChild) {
uni.showToast({
title: '请先选择孩子',
icon: 'none'
})
return
}
this.$navigateToPage(`/pages/parent/services/index`, {
childId: this.selectedChild.id
})
},
viewOrders() {
if (!this.selectedChild) {
uni.showToast({
title: '请先选择孩子',
icon: 'none'
})
return
}
this.$navigateToPage(`/pages/parent/orders/index`, {
childId: this.selectedChild.id
})
},
viewMessages() {
if (!this.selectedChild) {
uni.showToast({
title: '请先选择孩子',
icon: 'none'
})
return
}
this.$navigateToPage(`/pages/parent/messages/index`, {
childId: this.selectedChild.id
})
},
viewContracts() {
if (!this.selectedChild) {
uni.showToast({
title: '请先选择孩子',
icon: 'none'
})
return
}
this.$navigateToPage(`/pages/parent/contracts/index`, {
childId: this.selectedChild.id
})
}
}
}
</script>
<style lang="less" scoped>
.main_box {
background: #f8f9fa;
min-height: 100vh;
}
// 自定义导航栏
.navbar_section {
display: flex;
justify-content: center;
align-items: center;
background: #29D3B4;
.title {
padding: 40rpx 20rpx;
// 小程序端样式
// #ifdef MP-WEIXIN
padding: 80rpx 0 20rpx;
// #endif
font-size: 30rpx;
color: #fff;
}
}
// 家长信息
.parent_info_section {
background: #fff;
padding: 32rpx;
display: flex;
justify-content: space-between;
align-items: center;
.parent_name {
font-size: 32rpx;
font-weight: 600;
color: #333;
}
.parent_phone {
font-size: 24rpx;
color: #999;
}
}
// 弹窗样式
.child_popup {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.5);
display: flex;
justify-content: center;
align-items: center;
z-index: 1000;
.popup_content {
background: #fff;
border-radius: 16rpx;
width: 80%;
max-height: 70vh;
overflow: hidden;
.popup_header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 32rpx;
border-bottom: 1px solid #f0f0f0;
.popup_title {
font-size: 32rpx;
font-weight: 600;
color: #333;
}
.popup_close {
font-size: 48rpx;
color: #999;
font-weight: 300;
}
}
.popup_children_list {
max-height: 60vh;
overflow-y: auto;
.popup_child_item {
display: flex;
justify-content: space-between;
align-items: center;
padding: 24rpx 32rpx;
border-bottom: 1px solid #f8f9fa;
&.selected {
background: rgba(41, 211, 180, 0.1);
}
.popup_child_info {
flex: 1;
.popup_child_name {
font-size: 28rpx;
font-weight: 600;
color: #333;
margin-bottom: 8rpx;
}
.popup_child_details {
display: flex;
gap: 12rpx;
margin-bottom: 8rpx;
.popup_detail_tag {
font-size: 22rpx;
color: #666;
background: #f0f0f0;
padding: 2rpx 8rpx;
border-radius: 8rpx;
}
}
.popup_child_campus, .popup_child_class {
font-size: 22rpx;
color: #999;
margin-bottom: 4rpx;
}
}
.popup_child_courses {
font-size: 24rpx;
color: #29d3b4;
font-weight: 600;
}
}
}
}
}
// 选中孩子信息
.selected_child_section {
background: #fff;
margin: 20rpx;
border-radius: 16rpx;
padding: 32rpx;
box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.1);
.selected_child_header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 32rpx;
.selected_child_info {
flex: 1;
.selected_child_name {
font-size: 32rpx;
font-weight: 600;
color: #333;
margin-bottom: 8rpx;
}
.selected_child_details {
display: flex;
gap: 12rpx;
.selected_detail_tag {
font-size: 22rpx;
color: #666;
background: #f0f0f0;
padding: 4rpx 12rpx;
border-radius: 12rpx;
}
}
}
.switch_button {
background: #29d3b4;
color: #fff;
padding: 12rpx 24rpx;
border-radius: 20rpx;
font-size: 24rpx;
font-weight: 600;
}
}
.stats_grid {
display: flex;
justify-content: space-between;
align-items: center;
.stat_item {
display: flex;
flex-direction: column;
align-items: center;
gap: 8rpx;
.stat_number {
color: #29D3B4;
font-size: 48rpx;
font-weight: 600;
}
.stat_label {
color: #AAAAAA;
font-size: 24rpx;
}
}
}
}
.main_section {
margin-top: 20rpx;
background: #f8f9fa;
padding: 0 24rpx;
padding-top: 40rpx;
padding-bottom: 150rpx;
.grid_container {
background: #fff;
border-radius: 16rpx;
padding: 40rpx 20rpx;
display: flex;
flex-wrap: wrap;
justify-content: space-between;
.grid_item {
width: 30%;
margin-bottom: 40rpx;
display: flex;
flex-direction: column;
align-items: center;
&.empty_item {
// 空白占位项不显示任何内容
}
.grid_icon {
width: 88rpx;
height: 88rpx;
border-radius: 50%;
background: rgba(41, 211, 180, 0.1);
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 16rpx;
.icon_image {
width: 48rpx;
height: 48rpx;
}
}
.grid_text {
font-size: 26rpx;
color: #333;
text-align: center;
line-height: 1.2;
}
}
}
}
// 箭头图标样式
.arrow-icon {
width: 24rpx;
height: 24rpx;
opacity: 0.6;
}
</style>