<template>
|
<view class="page">
|
<image class="hero-image" :src="heroImage" mode="aspectFill" @error="replaceHero"></image>
|
<view class="hero-shade"></view>
|
<view class="custom-nav">
|
<view class="safe-space" :style="'height:' + navTop + 'px'"></view>
|
<view class="nav-row" :style="'height:' + navHeight + 'px;padding-right:' + navRight + 'px'">
|
<view class="back-button" @tap="goBack"><image src="/static/food-assets/arrow-left-white.svg" mode="aspectFit"></image></view>
|
<view class="capsule-space" :style="'width:' + navWidth + 'px'"></view>
|
</view>
|
</view>
|
|
<view class="content-sheet">
|
<view class="title-block"><text class="page-title">{{benefitTitle}}</text><view v-if="applicableCards != ''" class="talent-tag"><text>{{applicableCards}}</text></view></view>
|
<view class="tab-bar">
|
<view class="tab" :class="activeTab == 0 ? 'active' : ''" @tap="switchTab(0)">
|
<text>使用说明</text><view class="tab-line"></view>
|
</view>
|
<view class="tab" :class="activeTab == 1 ? 'active' : ''" @tap="switchTab(1)">
|
<text>学校地址</text><view class="tab-line"></view>
|
</view>
|
</view>
|
<view class="tab-content">
|
<view v-if="activeTab == 0" class="desc-card"><view v-if="benefitLoading" class="benefit-state"><view class="loading-spinner"></view><text>正在加载使用说明</text></view><view v-else-if="benefitError" class="benefit-state error-state"><text>使用说明加载失败</text><text class="retry-text" @tap="loadBenefit">重新加载</text></view><text v-else>{{description}}</text></view>
|
<scroll-view v-else class="school-scroll" scroll-y="true" :show-scrollbar="false">
|
<view v-if="schoolLoading" class="list-state"><view class="loading-spinner"></view><text>正在加载学校信息</text></view>
|
<view v-else-if="schoolError" class="list-state error-state"><text>学校信息加载失败</text><text class="retry-text" @tap="loadSchools">重新加载</text></view>
|
<view v-else-if="schoolLoaded && schools.length == 0" class="list-state"><text>暂无适用学校</text></view>
|
<view v-if="schoolLoaded && schools.length > 0" class="school-panel">
|
<view class="school-table-header"><view class="school-head-name"><text>学校名称</text></view><view class="school-head-action"></view></view>
|
<view class="school-row" v-for="item in schools" :key="item.id">
|
<view :class="item.detailAvailable ? 'school-name-cell' : 'school-name-cell is-disabled'" hover-class="school-name-cell-active" @tap="openSchoolDetail(item)"><text class="school-name-text">{{item.name}}</text></view>
|
<view class="school-actions">
|
<view :class="canNavigate(item) ? 'school-action' : 'school-action is-disabled'" @tap="openLocation(item)"><image src="/static/premium-assets/school-location.svg" mode="aspectFit"></image></view>
|
<view v-if="item.phone != ''" class="school-action" @tap="callSchool(item)"><image src="/static/premium-assets/school-phone.svg" mode="aspectFit"></image></view>
|
</view>
|
</view>
|
</view>
|
<view class="school-bottom-space"></view>
|
</scroll-view>
|
</view>
|
</view>
|
|
<view class="bottom-actions">
|
<view class="btn-outline" hover-class="btn-outline-active" @tap="showTalentCode">
|
<image src="/static/premium-assets/qr-code.png" mode="aspectFit"></image><text>出示人才码</text>
|
</view>
|
<view class="btn-fill" hover-class="btn-fill-active" @tap="goChildrenInfo">
|
<image src="/static/premium-assets/children-info.svg" mode="aspectFit"></image><text>子女信息</text>
|
</view>
|
</view>
|
</view>
|
</template>
|
|
<script setup lang="uts">
|
import { getChildrenEntrustmentBenefit, getChildrenEntrustmentSchools } from '../../services/portal.uts'
|
import { apiEnvironment } from '../../config/api.uts'
|
import { resolveApiUrl } from '../../services/http.uts'
|
import { getSession } from '../../services/session.uts'
|
import { safeBack } from '../../utils/navigation.uts'
|
|
const navTop = ref(28)
|
const navHeight = ref(32)
|
const navWidth = ref(88)
|
const navRight = ref(10)
|
const activeTab = ref(0)
|
const serviceId = ref('')
|
const talentId = ref('')
|
const heroImage = ref('')
|
const benefitTitle = ref('子女托管')
|
const applicableCards = ref('')
|
const description = ref('')
|
const benefitLoading = ref(true)
|
const benefitError = ref(false)
|
const schools = ref<any[]>([])
|
const schoolLoading = ref(true)
|
const schoolLoaded = ref(false)
|
const schoolError = ref(false)
|
|
onLoad((options: any) => {
|
// #ifdef MP-WEIXIN
|
const capsule = uni.getMenuButtonBoundingClientRect()
|
const info = uni.getSystemInfoSync()
|
navTop.value = capsule.top
|
navHeight.value = capsule.height
|
navWidth.value = capsule.width
|
navRight.value = info.windowWidth - capsule.right
|
// #endif
|
serviceId.value = options != null && options['serviceId'] != null ? options['serviceId'] as string : ''
|
const session = getSession()
|
if (session != null && session.talentId != null) talentId.value = session.talentId as string
|
if (talentId.value == '' && apiEnvironment == 'development') talentId.value = '2'
|
loadBenefit()
|
loadSchools()
|
})
|
const loadBenefit = () => {
|
if (serviceId.value == '') { benefitLoading.value = false; benefitError.value = true; return }
|
benefitLoading.value = true
|
benefitError.value = false
|
getChildrenEntrustmentBenefit(serviceId.value, talentId.value, (data: any) => {
|
benefitTitle.value = data.title || '子女托管'
|
applicableCards.value = data.applicableCards != null ? data.applicableCards as string : ''
|
heroImage.value = data.heroImage != null && data.heroImage != '' ? resolveApiUrl(data.heroImage as string) : ''
|
description.value = data.rightsText || '暂无使用说明'
|
benefitLoading.value = false
|
}, () => { benefitLoading.value = false; benefitError.value = true })
|
}
|
const loadSchools = () => {
|
schoolLoading.value = true
|
schoolLoaded.value = false
|
schoolError.value = false
|
if (serviceId.value == '') { schoolLoading.value = false; schoolError.value = true; return }
|
getChildrenEntrustmentSchools(serviceId.value, (data: any) => { schools.value = data instanceof Array ? data as any[] : []; schoolLoading.value = false; schoolLoaded.value = true }, () => { schoolLoading.value = false; schoolError.value = true })
|
}
|
const goBack = () => safeBack('/pages/premium-benefits/premium-benefits')
|
const switchTab = (index: number) => { activeTab.value = index }
|
const replaceHero = () => { heroImage.value = '' }
|
const openSchoolDetail = (item: any) => {
|
if (item.detailAvailable !== true) { uni.showToast({ title: '学校介绍暂未开放', icon: 'none' }); return }
|
uni.navigateTo({ url: '/pages/school-detail/school-detail?serviceId=' + encodeURIComponent(serviceId.value) + '&id=' + encodeURIComponent('' + item.id) + '&name=' + encodeURIComponent(item.name) + '&address=' + encodeURIComponent(item.address) })
|
}
|
const canNavigate = (item: any): boolean => Number(item.latitude) > 0 && Number(item.longitude) > 0
|
const openLocation = (item: any) => { if (!canNavigate(item)) { uni.showToast({ title: '学校暂未配置位置', icon: 'none' }); return }; uni.openLocation({ latitude: Number(item.latitude), longitude: Number(item.longitude), name: item.name, address: item.address, scale: 18, fail: () => uni.showToast({ title: '暂时无法打开地图导航', icon: 'none' }) }) }
|
const callSchool = (item: any) => { if (item.phone == null || item.phone == '') return; uni.makePhoneCall({ phoneNumber: item.phone, fail: () => uni.showToast({ title: '暂时无法拨打电话', icon: 'none' }) }) }
|
const showTalentCode = () => { const session = getSession(); const talentId = session != null && session.talentId != null ? session.talentId as string : (apiEnvironment == 'development' ? '2' : ''); uni.navigateTo({ url: '/pages/talent-code/talent-code?talentId=' + encodeURIComponent(talentId) + '&merchantId=' + encodeURIComponent(serviceId.value) + '&scene=children' }) }
|
const goChildrenInfo = () => uni.navigateTo({ url: '/pages/children-info/children-info' })
|
</script>
|
|
<style>
|
.page { width:100%; height:100vh; position:relative; overflow:hidden; background-color:#F5F5F5; }
|
.hero-image { position:absolute; left:0; right:0; top:0; width:100%; height:425rpx; background-color:#D4C8BE; }
|
.hero-shade { position:absolute; z-index:1; left:0; right:0; top:0; height:210rpx; background-image:linear-gradient(180deg,rgba(0,0,0,.45),rgba(0,0,0,0)); }
|
.custom-nav { position:absolute; z-index:10; left:0; right:0; top:0; }
|
.safe-space { height:28px; }
|
.nav-row { display:flex; box-sizing:border-box; padding-left:24rpx; flex-direction:row; align-items:center; justify-content:space-between; }
|
.back-button { display:flex; width:54rpx; height:54rpx; border-radius:50%; background-color:rgba(45,45,45,.48); justify-content:center; align-items:center; }
|
.back-button image { width:38rpx; height:38rpx; }
|
.capsule-space { height:100%; flex-shrink:0; }
|
.content-sheet { display:flex; position:absolute; z-index:3; left:0; right:0; top:405rpx; bottom:128rpx; bottom:calc(128rpx + env(safe-area-inset-bottom)); border-radius:30rpx 30rpx 0 0; background-color:#F5F5F5; flex-direction:column; }
|
.title-block { display:flex; box-sizing:border-box; padding:28rpx 32rpx 0; flex-direction:column; align-items:flex-start; flex-shrink:0; }
|
.page-title { color:#252525; font-size:35rpx; line-height:48rpx; font-weight:700; }
|
.talent-tag { display:flex; height:42rpx; margin-top:13rpx; box-sizing:border-box; padding:0 14rpx; border:1rpx solid #FFB98E; border-radius:5rpx; justify-content:center; align-items:center; }
|
.talent-tag text { color:#D87842; font-size:23rpx; line-height:30rpx; }
|
.tab-bar { display:flex; box-sizing:border-box; padding:0 32rpx; flex-direction:row; align-items:flex-start; flex-shrink:0; }
|
.tab { display:flex; margin-right:48rpx; padding-top:24rpx; flex-direction:column; align-items:center; flex-shrink:0; }
|
.tab text { color:#9A9A9A; font-size:30rpx; line-height:42rpx; font-weight:500; }
|
.tab.active text { color:#252525; font-weight:600; }
|
.tab-line { width:0; height:7rpx; margin-top:10rpx; border-radius:4rpx; background-image:linear-gradient(90deg,#FF4C56,#FFD43A); transition:width 180ms ease-out; }
|
.tab.active .tab-line { width:61rpx; }
|
.tab-content { display:flex; min-height:0; flex:1; flex-direction:column; }
|
.desc-card { display:flex; height:650rpx; margin:20rpx 26rpx 0; box-sizing:border-box; padding:28rpx 32rpx; border-radius:15rpx; background-color:#FFFFFF; flex-direction:column; flex-shrink:0; }
|
.desc-card text { color:#727983; font-size:25rpx; line-height:40rpx; }
|
.benefit-state { display:flex; min-height:0; flex:1; color:#9299A4; font-size:24rpx; justify-content:center; align-items:center; }.benefit-state.error-state { flex-direction:column; }
|
.school-scroll { min-height:0; flex:1; }
|
.list-state { display:flex; height:360rpx; flex-direction:row; justify-content:center; align-items:center; color:#9299A4; font-size:24rpx; }
|
.error-state { flex-direction:column; }
|
.retry-text { margin-top:20rpx; color:#F26A38; }
|
.loading-spinner { width:28rpx; height:28rpx; margin-right:13rpx; box-sizing:border-box; border:3rpx solid #FFD6C4; border-top-color:#FF6C2B; border-radius:50%; animation:school-loading 720ms linear infinite; }
|
@keyframes school-loading { from { transform:rotate(0deg); } to { transform:rotate(360deg); } }
|
.school-panel { margin: 16rpx 36rpx 0; overflow: hidden; border-width: 2rpx; border-style: solid; border-color: #DCE7FA; border-radius: 16rpx; background-color: #FFFFFF; }
|
.school-table-header { display: flex; min-height: 67rpx; background-color: #EEF4FF; flex-direction: row; align-items: center; }
|
.school-head-name { display: flex; min-width: 0; height: 67rpx; flex: 1; box-sizing: border-box; padding: 0 22rpx; justify-content: flex-start; align-items: center; }
|
.school-head-action { width: 126rpx; height: 67rpx; flex-shrink: 0; }
|
.school-head-name text { width: 100%; color: #26374F; font-size: 23rpx; font-weight: 700; text-align: left; }
|
.school-row { display: flex; height: 92rpx; min-height: 92rpx; border-top-width: 1rpx; border-top-style: solid; border-top-color: #E7ECF4; flex-direction: row; align-items: center; }
|
.school-name-cell { display: flex; min-width: 0; height: 92rpx; flex: 1; box-sizing: border-box; padding: 0 22rpx; align-items: center; justify-content: flex-start; }
|
.school-name-text { display:block; width:100%; min-width:0; height:92rpx; flex:1; color:#48566A; font-size:21rpx; line-height:92rpx; text-align:left; font-weight:600; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
|
.school-name-cell-active { background-color:#F5F8FD; }
|
.school-actions { display: flex; width: 126rpx; height: 92rpx; flex-direction: row; align-items: center; justify-content: space-evenly; flex-shrink: 0; }
|
.school-action { display: flex; width: 46rpx; height: 46rpx; box-sizing: border-box; border-width: 2rpx; border-style: solid; border-color: #B7D6FF; border-radius: 50%; background-color: #F1F7FF; justify-content: center; align-items: center; }
|
.school-action image { width: 27rpx; height: 27rpx; }
|
.is-disabled { opacity:.42; }
|
.school-bottom-space { height:calc(30rpx + env(safe-area-inset-bottom)); }
|
.bottom-actions { display:flex; position:absolute; z-index:8; left:0; right:0; bottom:0; height:128rpx; height:calc(128rpx + env(safe-area-inset-bottom)); box-sizing:border-box; padding:17rpx 31rpx 13rpx; padding-bottom:calc(13rpx + env(safe-area-inset-bottom)); background-color:#FFFFFF; flex-direction:row; justify-content:space-between; align-items:flex-start; }
|
.btn-outline { display:flex; flex:1; height:82rpx; margin-right:16rpx; box-sizing:border-box; border-radius:43rpx; background-image:linear-gradient(90deg,#FF4B32,#FF7E21); flex-direction:row; justify-content:center; align-items:center; }
|
.btn-outline image { width:32rpx; height:32rpx; margin-right:10rpx; }
|
.btn-outline text { color:#FFFFFF; font-size:28rpx; font-weight:600; }
|
.btn-outline-active { opacity:.7; }
|
.btn-fill { display:flex; flex:1; height:82rpx; margin-left:16rpx; border-radius:43rpx; background-image:linear-gradient(90deg,#FF4B32,#FF8A1E); flex-direction:row; justify-content:center; align-items:center; }
|
.btn-fill image { width:32rpx; height:32rpx; margin-right:10rpx; }
|
.btn-fill text { color:#FFFFFF; font-size:28rpx; font-weight:600; }
|
.btn-fill-active { opacity:.8; transform:scale(.99); }
|
</style>
|