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

493 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="provider-header">
<view class="provider-avatar">
<text class="avatar-emoji">🎓</text>
</view>
<view class="provider-info">
<text class="provider-name">{{ providerInfo.name || '服务商' }}</text>
<text class="provider-phone" v-if="providerInfo.phone">{{ providerInfo.phone }}</text>
<view class="provider-status">
<text class="status-tag" :class="providerInfo.status === 1 ? 'active' : ''">
{{ providerInfo.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/provider/course-list')">
<text class="stat-value">{{ stats.totalCourses }}</text>
<text class="stat-label">课程数</text>
</view>
<view class="stat-item" @click="goPage('/pages/provider/student-manage')">
<text class="stat-value">{{ stats.totalStudents }}</text>
<text class="stat-label">学生数</text>
</view>
<view class="stat-item" @click="goPage('/pages/provider/earnings')">
<text class="stat-value">¥{{ stats.totalEarnings }}</text>
<text class="stat-label">累计收益</text>
</view>
</view>
<!-- 快捷功能 -->
<view class="quick-actions">
<view class="action-item" @click="goPage('/pages/provider/course-manage')">
<text class="action-icon">📚</text>
<text class="action-text">课程管理</text>
</view>
<view class="action-item" @click="goPage('/pages/provider/checkin')">
<text class="action-icon"></text>
<text class="action-text">签到核销</text>
</view>
<view class="action-item" @click="goPage('/pages/provider/schedule')">
<text class="action-icon">📅</text>
<text class="action-text">课程安排</text>
</view>
<view class="action-item" @click="goPage('/pages/provider/withdraw')">
<text class="action-icon">💰</text>
<text class="action-text">提现</text>
</view>
</view>
<!-- 本月数据 -->
<view class="monthly-section">
<view class="section-title">本月数据</view>
<view class="monthly-grid">
<view class="monthly-item">
<text class="monthly-value">{{ stats.monthClasses }}</text>
<text class="monthly-label">上课次数</text>
</view>
<view class="monthly-item">
<text class="monthly-value">{{ stats.monthStudents }}</text>
<text class="monthly-label">新增学生</text>
</view>
<view class="monthly-item">
<text class="monthly-value">¥{{ stats.monthEarnings }}</text>
<text class="monthly-label">本月收益</text>
</view>
<view class="monthly-item">
<text class="monthly-value">{{ stats.satisfaction }}%</text>
<text class="monthly-label">满意度</text>
</view>
</view>
</view>
<!-- 功能菜单 -->
<view class="menu-section">
<view class="menu-item" @click="goPage('/pages/provider/course-manage')">
<text class="menu-icon">📚</text>
<text class="menu-text">课程管理</text>
<text class="arrow"></text>
</view>
<view class="menu-item" @click="goPage('/pages/provider/student-manage')">
<text class="menu-icon">👨🎓</text>
<text class="menu-text">学生管理</text>
<text class="arrow"></text>
</view>
<view class="menu-item" @click="goPage('/pages/provider/schedule')">
<text class="menu-icon">📅</text>
<text class="menu-text">课程安排</text>
<text class="arrow"></text>
</view>
<view class="menu-item" @click="goPage('/pages/provider/checkin')">
<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/provider/earnings')">
<text class="menu-icon">💰</text>
<text class="menu-text">收益查看</text>
<text class="arrow"></text>
</view>
<view class="menu-item" @click="goPage('/pages/provider/withdraw')">
<text class="menu-icon">💳</text>
<text class="menu-text">提取收益</text>
<text class="arrow"></text>
</view>
<view class="menu-item" @click="goPage('/pages/wallet/transaction')">
<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/provider/info')">
<text class="menu-icon">🏢</text>
<text class="menu-text">机构资料</text>
<text class="arrow"></text>
</view>
<view class="menu-item" @click="goPage('/pages/provider/teachers')">
<text class="menu-icon">👨🏫</text>
<text class="menu-text">师资管理</text>
<text class="arrow"></text>
</view>
<view class="menu-item" @click="goPage('/pages/provider/reviews')">
<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 {
providerInfo: {},
stats: {
totalCourses: 0,
totalStudents: 0,
totalEarnings: 0,
monthClasses: 0,
monthStudents: 0,
monthEarnings: 0,
satisfaction: 0
}
}
},
onShow() {
this.loadProviderInfo()
this.loadStats()
},
methods: {
loadProviderInfo() {
const userInfo = uni.getStorageSync('userInfo')
if (userInfo) {
this.providerInfo = {
name: userInfo.name || '服务商',
phone: userInfo.phone,
status: userInfo.status || 1
}
}
},
async loadStats() {
try {
const stats = await api.providerApi.getEarningsStats()
this.stats = {
totalCourses: stats.totalCourses || 0,
totalStudents: stats.totalStudents || 0,
totalEarnings: stats.totalIncome || 0,
monthClasses: stats.monthClasses || 0,
monthStudents: stats.monthStudents || 0,
monthEarnings: stats.monthIncome || 0,
satisfaction: stats.satisfaction || 0
}
} catch (err) {
console.error('加载统计数据失败', err)
// 失败时使用默认值
this.stats = {
totalCourses: 0,
totalStudents: 0,
totalEarnings: 0,
monthClasses: 0,
monthStudents: 0,
monthEarnings: 0,
satisfaction: 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;
}
.provider-header {
background: linear-gradient(135deg, $primary-color 0%, $primary-light 100%);
padding: 60rpx 30rpx 40rpx;
display: flex;
align-items: center;
.provider-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;
}
}
.provider-info {
flex: 1;
.provider-name {
display: block;
font-size: 36rpx;
font-weight: bold;
color: #fff;
margin-bottom: 12rpx;
}
.provider-phone {
display: block;
font-size: 26rpx;
color: rgba(255, 255, 255, 0.8);
margin-bottom: 12rpx;
}
.provider-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 {
display: flex;
flex-direction: column;
align-items: center;
.action-icon {
font-size: 48rpx;
margin-bottom: 12rpx;
}
.action-text {
font-size: 24rpx;
color: #666;
}
}
}
.monthly-section {
background: #fff;
margin: 20rpx 30rpx;
border-radius: 16rpx;
padding: 30rpx;
.section-title {
font-size: 28rpx;
color: #999;
margin-bottom: 24rpx;
}
.monthly-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 24rpx;
.monthly-item {
display: flex;
flex-direction: column;
align-items: center;
padding: 24rpx;
background: #f8f8f8;
border-radius: 12rpx;
.monthly-value {
font-size: 32rpx;
font-weight: bold;
color: $primary-color;
margin-bottom: 8rpx;
}
.monthly-label {
font-size: 24rpx;
color: #999;
}
}
}
}
.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;
&:last-child {
border-bottom: none;
}
.menu-icon {
font-size: 40rpx;
margin-right: 20rpx;
}
.menu-text {
flex: 1;
font-size: 30rpx;
color: #333;
}
.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>