peixue-dev/peidu/uniapp/manager-package/pages/manager/index.vue

472 lines
12 KiB
Vue
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view class="container">
<!-- 管理师信息头部 -->
<view class="manager-header">
<view class="manager-avatar">
<text class="avatar-emoji">👔</text>
</view>
<view class="manager-info">
<text class="manager-name">{{ managerInfo.name || '管理师' }}</text>
<text class="manager-phone" v-if="managerInfo.phone">{{ managerInfo.phone }}</text>
<view class="manager-status">
<text class="status-tag" :class="managerInfo.status === 1 ? 'active' : ''">
{{ managerInfo.status === 1 ? '✅ 已认证' : '⏳ 待审核' }}
</text>
</view>
</view>
<view class="setting-btn" @click="goSetting">
<text>设置</text>
</view>
</view>
<!-- 数据统计 -->
<view class="stats-section">
<view class="stat-item" @click="goPage('/pages/manager/work-orders')">
<text class="stat-value">{{ stats.totalOrders }}</text>
<text class="stat-label">管理工单</text>
</view>
<view class="stat-item" @click="goPage('/pages/manager/work-orders?status=pending')">
<text class="stat-value">{{ stats.pendingOrders }}</text>
<text class="stat-label">待处理</text>
</view>
<view class="stat-item">
<text class="stat-value">{{ stats.teacherCount }}</text>
<text class="stat-label">陪伴员数</text>
</view>
</view>
<!-- 快捷功能 -->
<view class="quick-actions">
<view class="action-item" @click="goPage('/pages/manager/work-orders')">
<text class="action-icon">📋</text>
<text class="action-text">工单管理</text>
<text class="badge" v-if="stats.pendingOrders">{{ stats.pendingOrders }}</text>
</view>
<view class="action-item" @click="goPage('/manager-package/pages/manager/dispatch-list')">
<text class="action-icon">👥</text>
<text class="action-text">派单管理</text>
</view>
<view class="action-item" @click="goPage('/pages/manager/teachers')">
<text class="action-icon">👨🏫</text>
<text class="action-text">陪伴员管理</text>
</view>
<view class="action-item" @click="goPage('/pages/manager/statistics')">
<text class="action-icon">📊</text>
<text class="action-text">数据统计</text>
</view>
</view>
<!-- 工单管理 -->
<view class="menu-section">
<view class="section-title">工单管理</view>
<view class="menu-item" @click="goPage('/pages/manager/work-orders')">
<text class="menu-icon">📋</text>
<text class="menu-text">全部工单</text>
<text class="arrow"></text>
</view>
<view class="menu-item" @click="goPage('/pages/manager/work-orders?status=pending')">
<text class="menu-icon"></text>
<text class="menu-text">待处理工单</text>
<text class="badge" v-if="stats.pendingOrders">{{ stats.pendingOrders }}</text>
<text class="arrow"></text>
</view>
<view class="menu-item" @click="goPage('/manager-package/pages/manager/dispatch-list')">
<text class="menu-icon">👥</text>
<text class="menu-text">派单管理</text>
<text class="arrow"></text>
</view>
</view>
<!-- 陪伴员管理 -->
<view class="menu-section">
<view class="section-title">陪伴员管理</view>
<view class="menu-item" @click="goPage('/pages/manager/teachers')">
<text class="menu-icon">👨🏫</text>
<text class="menu-text">陪伴员列表</text>
<text class="arrow"></text>
</view>
<view class="menu-item" @click="goPage('/pages/manager/teacher-apply')">
<text class="menu-icon">📝</text>
<text class="menu-text">申请审核</text>
<text class="arrow"></text>
</view>
<view class="menu-item" @click="goPage('/pages/manager/teacher-schedule')">
<text class="menu-icon">📅</text>
<text class="menu-text">排班管理</text>
<text class="arrow"></text>
</view>
</view>
<!-- 数据与报表 -->
<view class="menu-section">
<view class="section-title">数据与报表</view>
<view class="menu-item" @click="goPage('/pages/manager/statistics')">
<text class="menu-icon">📊</text>
<text class="menu-text">数据统计</text>
<text class="arrow"></text>
</view>
<view class="menu-item" @click="goPage('/pages/manager/reports')">
<text class="menu-icon">📈</text>
<text class="menu-text">报表分析</text>
<text class="arrow"></text>
</view>
</view>
<!-- 其他功能 -->
<view class="menu-section">
<view class="menu-item" @click="contactService">
<text class="menu-icon">💬</text>
<text class="menu-text">联系客服</text>
<text class="arrow"></text>
</view>
<view class="menu-item" @click="goPage('/pages/feedback/create')">
<text class="menu-icon">📝</text>
<text class="menu-text">意见反馈</text>
<text class="arrow"></text>
</view>
</view>
<!-- 退出登录 -->
<view class="logout-section">
<button class="btn-logout" @click="handleLogout">退出登录</button>
</view>
</view>
</template>
<script>
export default {
data() {
return {
managerInfo: {},
stats: {
totalOrders: 0,
pendingOrders: 0,
teacherCount: 0
}
}
},
onShow() {
console.log('[管理师首页] onShow - 重新加载数据')
this.loadManagerInfo()
this.loadStats()
},
mounted() {
// 🔥 新增:监听全局刷新事件
console.log('[管理师首页] mounted - 注册刷新事件监听')
uni.$on('refreshPendingOrders', this.handleRefresh)
uni.$on('refreshManagerBooking', this.handleRefresh)
},
beforeDestroy() {
// 🔥 新增:移除事件监听
console.log('[管理师首页] beforeDestroy - 移除刷新事件监听')
uni.$off('refreshPendingOrders', this.handleRefresh)
uni.$off('refreshManagerBooking', this.handleRefresh)
},
methods: {
// 🔥 新增:处理刷新事件
handleRefresh() {
console.log('[管理师首页] handleRefresh - 收到刷新事件,重新加载统计数据')
this.loadStats()
},
loadManagerInfo() {
const userInfo = uni.getStorageSync('userInfo')
if (userInfo) {
this.managerInfo = {
name: userInfo.name || '管理师',
phone: userInfo.phone,
status: userInfo.status || 1
}
}
},
async loadStats() {
try {
console.log('[管理师首页] 开始加载统计数据')
const userInfo = uni.getStorageSync('userInfo')
console.log('[管理师首页] userInfo:', userInfo)
console.log('[管理师首页] managerId:', userInfo.id)
const stats = await api.managerApi.getStatistics(userInfo.id)
console.log('[管理师首页] 后端返回的统计数据:', stats)
console.log('[管理师首页] pendingOrders:', stats.pendingOrders)
this.stats = {
totalOrders: stats.totalOrders || 0,
pendingOrders: stats.pendingOrders || 0,
teacherCount: stats.totalTeachers || 0
}
console.log('[管理师首页] 更新后的stats:', this.stats)
} catch (err) {
console.error('[管理师首页] 加载统计数据失败', err)
// 失败时使用默认值
this.stats = {
totalOrders: 0,
pendingOrders: 0,
teacherCount: 0
}
}
},
goSetting() {
uni.navigateTo({
url: '/pages/user/profile'
})
},
goPage(url) {
uni.navigateTo({ url })
},
contactService() {
uni.showToast({
title: '客服功能开发中',
icon: 'none'
})
},
handleLogout() {
uni.showModal({
title: '提示',
content: '确定要退出登录吗?',
success: (res) => {
if (res.confirm) {
uni.removeStorageSync('token')
uni.removeStorageSync('userInfo')
uni.reLaunch({
url: '/pages/index/index'
})
}
}
})
}
}
}
</script>
<style lang="scss" scoped>
@import '@/static/css/common.scss';
.container {
min-height: 100vh;
background: #f8f8f8;
padding-bottom: 40rpx;
}
.manager-header {
background: linear-gradient(135deg, $primary-color 0%, $primary-light 100%);
padding: 60rpx 30rpx 40rpx;
display: flex;
align-items: center;
.manager-avatar {
width: 120rpx;
height: 120rpx;
border-radius: 60rpx;
border: 4rpx solid rgba(255, 255, 255, 0.3);
margin-right: 24rpx;
background: rgba(255, 255, 255, 0.2);
display: flex;
align-items: center;
justify-content: center;
.avatar-emoji {
font-size: 60rpx;
}
}
.manager-info {
flex: 1;
.manager-name {
display: block;
font-size: 36rpx;
font-weight: bold;
color: #fff;
margin-bottom: 12rpx;
}
.manager-phone {
display: block;
font-size: 26rpx;
color: rgba(255, 255, 255, 0.8);
margin-bottom: 12rpx;
}
.manager-status {
.status-tag {
display: inline-block;
padding: 4rpx 16rpx;
background: rgba(255, 255, 255, 0.2);
border-radius: 20rpx;
font-size: 22rpx;
color: #fff;
border: 1rpx solid rgba(255, 255, 255, 0.3);
&.active {
background: rgba(82, 196, 26, 0.3);
border-color: rgba(82, 196, 26, 0.5);
}
}
}
}
.setting-btn {
color: #fff;
font-size: 28rpx;
padding: 12rpx 24rpx;
background: rgba(255, 255, 255, 0.2);
border-radius: 30rpx;
}
}
.stats-section {
background: #fff;
margin: 20rpx 30rpx;
border-radius: 16rpx;
padding: 30rpx;
display: flex;
justify-content: space-around;
.stat-item {
display: flex;
flex-direction: column;
align-items: center;
.stat-value {
font-size: 36rpx;
font-weight: bold;
color: $primary-color;
margin-bottom: 8rpx;
}
.stat-label {
font-size: 24rpx;
color: #999;
}
}
}
.quick-actions {
background: #fff;
margin: 20rpx 30rpx;
border-radius: 16rpx;
padding: 30rpx;
display: flex;
justify-content: space-around;
.action-item {
position: relative;
display: flex;
flex-direction: column;
align-items: center;
.action-icon {
font-size: 48rpx;
margin-bottom: 12rpx;
}
.action-text {
font-size: 24rpx;
color: #666;
}
.badge {
position: absolute;
top: -8rpx;
right: -16rpx;
min-width: 32rpx;
height: 32rpx;
background: #ff4d4f;
color: #fff;
font-size: 20rpx;
border-radius: 16rpx;
padding: 0 8rpx;
display: flex;
align-items: center;
justify-content: center;
}
}
}
.menu-section {
background: #fff;
margin: 20rpx 30rpx;
border-radius: 16rpx;
overflow: hidden;
.section-title {
padding: 24rpx 30rpx 12rpx;
font-size: 28rpx;
color: #999;
font-weight: 500;
}
.menu-item {
display: flex;
align-items: center;
padding: 32rpx 30rpx;
border-bottom: 1rpx solid #f0f0f0;
position: relative;
&:last-child {
border-bottom: none;
}
.menu-icon {
font-size: 40rpx;
margin-right: 20rpx;
}
.menu-text {
flex: 1;
font-size: 30rpx;
color: #333;
}
.badge {
min-width: 32rpx;
height: 32rpx;
background: #ff4d4f;
color: #fff;
font-size: 20rpx;
border-radius: 16rpx;
padding: 0 8rpx;
display: flex;
align-items: center;
justify-content: center;
margin-right: 12rpx;
}
.arrow {
font-size: 32rpx;
color: #999;
}
}
}
.logout-section {
margin: 40rpx 30rpx;
.btn-logout {
width: 100%;
height: 88rpx;
background: #fff;
color: #ff4d4f;
border: 1rpx solid #ff4d4f;
border-radius: 44rpx;
font-size: 32rpx;
display: flex;
align-items: center;
justify-content: center;
&::after {
border: none;
}
}
}
</style>