487 lines
13 KiB
Vue
487 lines
13 KiB
Vue
<template>
|
||
<page-meta :page-style="$theme.pageStyle">
|
||
<!-- #ifndef H5 -->
|
||
<navigation-bar :front-color="$theme.navColor" :background-color="$theme.navBgColor" />
|
||
<!-- #endif -->
|
||
</page-meta>
|
||
<view class="index">
|
||
<!-- 顶部区域:Logo + 欢迎文字 + 首页图片 -->
|
||
<view class="header-section">
|
||
<image
|
||
:src="schoolLogoSrc"
|
||
mode="aspectFit"
|
||
class="school-logo"
|
||
/>
|
||
<view class="welcome-text">
|
||
<view class="title" v-if="isTeacher">您好,招生老师</view>
|
||
<view class="title" v-else>欢迎来到预报名系统</view>
|
||
<view class="subtitle" v-if="isTeacher">祝您招生顺利,业绩长虹!</view>
|
||
<view class="subtitle" v-else>请选择下方功能开始操作</view>
|
||
</view>
|
||
<image
|
||
:src="homeImageSrc"
|
||
mode="widthFix"
|
||
class="home-image"
|
||
/>
|
||
|
||
<!-- 快捷操作标题 -->
|
||
<view class="section-title" v-if="isLogin && isTeacher">
|
||
<view class="title-icon"></view>
|
||
<text>快捷操作</text>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 主要内容区域 -->
|
||
<view class="main-content">
|
||
<!-- 招生老师:快捷操作入口 -->
|
||
<view class="quick-actions" v-if="isLogin && isTeacher">
|
||
<view class="action-item" @click="goToPreRegistration">
|
||
<view class="action-icon blue">
|
||
<u-icon name="edit-pen" size="40" color="#FFFFFF"></u-icon>
|
||
</view>
|
||
<text class="action-text">预报名</text>
|
||
</view>
|
||
<view class="action-item" @click="goToMyRecruitment">
|
||
<view class="action-icon green">
|
||
<u-icon name="list" size="40" color="#FFFFFF"></u-icon>
|
||
</view>
|
||
<text class="action-text">我的招生</text>
|
||
</view>
|
||
<view class="action-item" @click="goToPayment">
|
||
<view class="action-icon orange">
|
||
<u-icon name="rmb-circle" size="40" color="#FFFFFF"></u-icon>
|
||
</view>
|
||
<text class="action-text">缴费</text>
|
||
</view>
|
||
<view class="action-item" @click="goToUser">
|
||
<view class="action-icon purple">
|
||
<u-icon name="account" size="40" color="#FFFFFF"></u-icon>
|
||
</view>
|
||
<text class="action-text">个人中心</text>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 学生:功能入口 -->
|
||
<view class="quick-actions" v-if="isLogin && !isTeacher">
|
||
<view class="action-item" @click="goToPreRegistration">
|
||
<view class="action-icon blue">
|
||
<u-icon name="edit-pen" size="40" color="#FFFFFF"></u-icon>
|
||
</view>
|
||
<text class="action-text">预报名</text>
|
||
</view>
|
||
<view class="action-item" @click="goToPayment">
|
||
<view class="action-icon orange">
|
||
<u-icon name="rmb-circle" size="40" color="#FFFFFF"></u-icon>
|
||
</view>
|
||
<text class="action-text">缴费</text>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 未登录提示 -->
|
||
<view class="login-tip" v-if="!isLogin">
|
||
<view class="tip-icon">🔒</view>
|
||
<view class="tip-text">登录后查看更多功能</view>
|
||
<view class="tip-button" @click="goToLogin">立即登录</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- #ifdef H5 -->
|
||
<view class="footer" v-if="isH5">
|
||
<router-navigate
|
||
class="footer-link"
|
||
:to="{
|
||
path: '/pages/webview/webview',
|
||
query: {
|
||
url: item.value
|
||
}
|
||
}"
|
||
v-for="item in appStore.getCopyrightConfig"
|
||
:key="item.key"
|
||
>
|
||
{{ item.key }}
|
||
</router-navigate>
|
||
</view>
|
||
<!-- #endif -->
|
||
|
||
<!-- 返回顶部按钮 -->
|
||
<u-back-top
|
||
:scroll-top="scrollTop"
|
||
:top="100"
|
||
:customStyle="{
|
||
backgroundColor: '#FFF',
|
||
color: '#000',
|
||
boxShadow: '0px 3px 6px rgba(0, 0, 0, 0.1)'
|
||
}"
|
||
>
|
||
</u-back-top>
|
||
|
||
<!-- #ifdef MP -->
|
||
<!-- 微信小程序隐私弹窗 -->
|
||
<MpPrivacyPopup></MpPrivacyPopup>
|
||
<!-- #endif -->
|
||
<tabbar />
|
||
</view>
|
||
</template>
|
||
|
||
<script setup lang="ts">
|
||
import { getIndex } from '@/api/shop'
|
||
import { getEnrollmentStatistical, getTeacherInfo } from '@/api/app'
|
||
import { onLoad, onShow } from '@dcloudio/uni-app'
|
||
import { computed, reactive, ref } from 'vue'
|
||
import { useAppStore } from '@/stores/app'
|
||
import { useUserStore } from '@/stores/user'
|
||
import { storeToRefs } from 'pinia'
|
||
import { getAliyunImageUrl } from '@/utils/imageUtils'
|
||
import { ensureStorageConfig } from '@/utils/configUtils'
|
||
|
||
// #ifdef MP
|
||
import MpPrivacyPopup from './component/mp-privacy-popup.vue'
|
||
// #endif
|
||
|
||
const appStore = useAppStore()
|
||
const userStore = useUserStore()
|
||
const { isLogin, userInfo, isTeacher } = storeToRefs(userStore)
|
||
|
||
const state = reactive<{
|
||
pages: any[]
|
||
meta: any[]
|
||
article: any[]
|
||
}>({
|
||
pages: [],
|
||
meta: [],
|
||
article: []
|
||
})
|
||
|
||
const scrollTop = ref<number>(0)
|
||
const stats = ref({
|
||
total: 0,
|
||
today: 0,
|
||
week: 0
|
||
})
|
||
|
||
const isH5 = ref(false)
|
||
// #ifdef H5
|
||
isH5.value = true
|
||
// #endif
|
||
|
||
const getData = async () => {
|
||
try {
|
||
const data = await getIndex()
|
||
if (data?.page?.data) {
|
||
state.pages = JSON.parse(data.page.data)
|
||
}
|
||
if (data?.page?.meta) {
|
||
state.meta = JSON.parse(data.page.meta)
|
||
}
|
||
state.article = data?.article || []
|
||
} catch (error) {
|
||
console.error('获取首页数据失败:', error)
|
||
}
|
||
}
|
||
|
||
const getStats = async () => {
|
||
if (!isLogin.value) {
|
||
return
|
||
}
|
||
|
||
try {
|
||
// 先获取教师信息,获取 teacherId
|
||
let teacherId: number | undefined = undefined
|
||
|
||
// 尝试从 userInfo 中获取
|
||
if (userInfo.value?.teacherId) {
|
||
teacherId = userInfo.value.teacherId
|
||
} else {
|
||
// 如果 userInfo 中没有,调用 getTeacherInfo 获取
|
||
try {
|
||
const teacherRes = await getTeacherInfo({ id: userInfo.value.id })
|
||
if (teacherRes && teacherRes.code === 1 && teacherRes.data) {
|
||
teacherId = teacherRes.data.teacherId
|
||
// 更新 userInfo
|
||
userInfo.value.teacherId = teacherId
|
||
}
|
||
} catch (error) {
|
||
console.error('获取教师信息失败:', error)
|
||
}
|
||
}
|
||
|
||
if (teacherId) {
|
||
console.log('首页获取招生统计,teacherId:', teacherId)
|
||
const res = await getEnrollmentStatistical(teacherId)
|
||
// 接口直接返回数据对象,没有 code 包装
|
||
if (res && res.total_enroll_count !== undefined) {
|
||
stats.value = {
|
||
total: res.total_enroll_count,
|
||
today: res.today_enroll_count,
|
||
week: res.week_enroll_count
|
||
}
|
||
}
|
||
} else {
|
||
console.log('未找到 teacherId,跳过获取招生统计')
|
||
}
|
||
} catch (error) {
|
||
console.error('获取招生统计失败:', error)
|
||
}
|
||
}
|
||
|
||
const goToPreRegistration = () => {
|
||
uni.navigateTo({
|
||
url: '/pages/pre_registration/pre_registration'
|
||
})
|
||
}
|
||
|
||
const goToMyRecruitment = () => {
|
||
uni.navigateTo({
|
||
url: '/pages/my_recruitment/my_recruitment'
|
||
})
|
||
}
|
||
|
||
const goToUser = () => {
|
||
uni.reLaunch({
|
||
url: '/pages/user/user'
|
||
})
|
||
}
|
||
|
||
const goToPayment = () => {
|
||
uni.navigateTo({
|
||
url: '/pages/payment/payment'
|
||
})
|
||
}
|
||
|
||
const goToLogin = () => {
|
||
uni.navigateTo({
|
||
url: '/pages/login/login'
|
||
})
|
||
}
|
||
|
||
// 初始化图片源
|
||
const schoolLogoSrc = ref(getAliyunImageUrl('static/yubaoming/school_logo.png'))
|
||
const homeImageSrc = ref(getAliyunImageUrl('static/yubaoming/home.png'))
|
||
|
||
const initImageSources = async () => {
|
||
await ensureStorageConfig()
|
||
schoolLogoSrc.value = getAliyunImageUrl('static/yubaoming/school_logo.png')
|
||
homeImageSrc.value = getAliyunImageUrl('static/yubaoming/home.png')
|
||
}
|
||
|
||
const shareQrcode = () => {
|
||
uni.reLaunch({
|
||
url: '/pages/user/user'
|
||
})
|
||
setTimeout(() => {
|
||
uni.$emit('openQrcodeModal')
|
||
}, 300)
|
||
}
|
||
|
||
onLoad((options: any) => {
|
||
initImageSources()
|
||
getData()
|
||
|
||
if (options.scene) {
|
||
const invitationCode = decodeURIComponent(options.scene)
|
||
if (isLogin.value) {
|
||
uni.navigateTo({
|
||
url: `/pages/pre_registration/pre_registration?invitationCode=${invitationCode}`
|
||
})
|
||
} else {
|
||
uni.navigateTo({
|
||
url: `/pages/login/login?invitationCode=${invitationCode}`
|
||
})
|
||
}
|
||
}
|
||
})
|
||
|
||
onShow(async () => {
|
||
// 等待登录状态确定
|
||
await new Promise(resolve => setTimeout(resolve, 100))
|
||
|
||
// 如果没有登录,跳过
|
||
if (!isLogin.value) {
|
||
return
|
||
}
|
||
|
||
// 如果 userInfo 中没有用户信息,先调用 getUser 获取用户信息
|
||
if (!userInfo.value?.id) {
|
||
await userStore.getUser()
|
||
}
|
||
|
||
// 获取招生统计(getStats 内部会处理获取 teacherId)
|
||
getStats()
|
||
})
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
.index {
|
||
min-height: 100vh;
|
||
background-color: #F5F7FA;
|
||
padding-bottom: calc(20rpx + env(safe-area-inset-bottom));
|
||
}
|
||
|
||
/* 顶部区域 */
|
||
.header-section {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
padding: 40rpx 30rpx;
|
||
position: relative;
|
||
|
||
.school-logo {
|
||
width: 350rpx;
|
||
height: 350rpx;
|
||
margin-top: -40rpx;
|
||
margin-bottom: -80rpx;
|
||
}
|
||
|
||
.welcome-text {
|
||
text-align: center;
|
||
margin-bottom: -100rpx;
|
||
|
||
.title {
|
||
font-size: 40rpx;
|
||
font-weight: 600;
|
||
color: #000000;
|
||
margin-bottom: 12rpx;
|
||
}
|
||
.subtitle {
|
||
font-size: 28rpx;
|
||
color: #333333;
|
||
}
|
||
}
|
||
|
||
.home-image {
|
||
width: calc(100% + 60rpx);
|
||
margin-left: -30rpx;
|
||
margin-right: -30rpx;
|
||
}
|
||
}
|
||
|
||
/* 主要内容区域 */
|
||
.main-content {
|
||
padding: 0 30rpx 30rpx;
|
||
position: relative;
|
||
z-index: 1;
|
||
}
|
||
|
||
/* 快捷操作标题 */
|
||
.section-title {
|
||
display: flex;
|
||
align-items: center;
|
||
font-size: 32rpx;
|
||
font-weight: 600;
|
||
color: #000000;
|
||
padding: 20rpx 0;
|
||
position: absolute;
|
||
bottom: 50rpx;
|
||
left: 30rpx;
|
||
z-index: 10;
|
||
|
||
.title-icon {
|
||
margin-right: 12rpx;
|
||
width: 10rpx;
|
||
height: 32rpx;
|
||
background: linear-gradient(135deg, #3B82F6 0%, #2563EB 100%);
|
||
border-radius: 3rpx;
|
||
}
|
||
}
|
||
|
||
/* 快捷操作 */
|
||
.quick-actions {
|
||
display: flex;
|
||
flex-direction: row;
|
||
justify-content: space-between;
|
||
gap: 20rpx;
|
||
margin-top: -30rpx;
|
||
|
||
.action-item {
|
||
flex: 1;
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
background: #FFFFFF;
|
||
border-radius: 24rpx;
|
||
padding: 30rpx 20rpx;
|
||
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.06);
|
||
|
||
&:active {
|
||
opacity: 0.7;
|
||
}
|
||
|
||
.action-icon {
|
||
width: 100rpx;
|
||
height: 100rpx;
|
||
border-radius: 24rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
margin-bottom: 16rpx;
|
||
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.1);
|
||
|
||
&.blue {
|
||
background: linear-gradient(135deg, #3B82F6 0%, #2563EB 100%);
|
||
}
|
||
&.green {
|
||
background: linear-gradient(135deg, #10B981 0%, #059669 100%);
|
||
}
|
||
&.purple {
|
||
background: linear-gradient(135deg, #8B5CF6 0%, #7C3AED 100%);
|
||
}
|
||
&.orange {
|
||
background: linear-gradient(135deg, #F59E0B 0%, #D97706 100%);
|
||
}
|
||
}
|
||
|
||
.action-text {
|
||
font-size: 26rpx;
|
||
color: #1F2937;
|
||
font-weight: 500;
|
||
}
|
||
}
|
||
}
|
||
|
||
/* 未登录提示 */
|
||
.login-tip {
|
||
background: #FFFFFF;
|
||
border-radius: 24rpx;
|
||
padding: 60rpx 40rpx;
|
||
text-align: center;
|
||
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.06);
|
||
|
||
.tip-icon {
|
||
font-size: 80rpx;
|
||
margin-bottom: 20rpx;
|
||
}
|
||
|
||
.tip-text {
|
||
font-size: 30rpx;
|
||
color: #6B7280;
|
||
margin-bottom: 30rpx;
|
||
}
|
||
|
||
.tip-button {
|
||
display: inline-block;
|
||
background: linear-gradient(135deg, #3B82F6 0%, #2563EB 100%);
|
||
color: #FFFFFF;
|
||
font-size: 30rpx;
|
||
font-weight: 500;
|
||
padding: 20rpx 60rpx;
|
||
border-radius: 40rpx;
|
||
|
||
&:active {
|
||
opacity: 0.9;
|
||
}
|
||
}
|
||
}
|
||
|
||
/* 底部 */
|
||
.footer {
|
||
padding: 40rpx 30rpx;
|
||
text-align: center;
|
||
|
||
.footer-link {
|
||
font-size: 24rpx;
|
||
color: #9CA3AF;
|
||
margin: 0 16rpx;
|
||
}
|
||
}
|
||
</style>
|