Files
yunzerwebsiteallinone/uniapp/pages/sub/tabs.vue
T

182 lines
4.5 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
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="page">
<!-- 顶部子系统标识条 -->
<view v-if="sub" class="hero" :class="sub.tint" :style="headPad">
<view class="hero-back" @tap="goBackNav">
<FaIcon name="chevron-left" color="#ffffff" :size="14" />
</view>
<view class="hero-main">
<view class="hero-icon">
<FaIcon :name="sub.icon" color="#ffffff" :size="24" />
</view>
<view class="hero-meta">
<text class="hero-name">{{ sub.title }}</text>
<text class="hero-desc">{{ sub.desc }}</text>
</view>
</view>
</view>
<!--
内容区:三页签共用底部 tabbar,H5 / APK / 微信小程序结构完全一致。
各自独立 scroll-view(保留各自滚动位置);首页进入即挂载,
其余页签首次切换才挂载,之后用 v-show 保留状态。
-->
<view v-if="sub" class="content">
<scroll-view v-if="visited.home" v-show="activeTab === 'home'" class="pane" scroll-y>
<SubHome :slug="slug" embedded @switch-tab="switchByIndex" @back="goBackNav" />
<view class="pane-bottom" />
</scroll-view>
<scroll-view v-if="visited.functions" v-show="activeTab === 'functions'" class="pane" scroll-y>
<SubFunctions :slug="slug" embedded @switch-tab="switchByIndex" @back="goBackNav" />
<view class="pane-bottom" />
</scroll-view>
<scroll-view v-if="visited.mine" v-show="activeTab === 'mine'" class="pane" scroll-y>
<SubMine :slug="slug" embedded @switch-tab="switchByIndex" @back="goBackNav" />
<view class="pane-bottom" />
</scroll-view>
</view>
<AppTabbar variant="switch" :current="activeTab" :tabs="tabs" @change="onTabChange" />
</view>
</template>
<script setup>
import { ref } from 'vue'
import { onLoad } from '@dcloudio/uni-app'
import { getSubsystem } from '@/config/subsystems.js'
import { mpHeadPad } from '@/utils/mpHead.js'
import AppTabbar from '@/components/AppTabbar.vue'
import SubHome from '@/components/sub/SubHome.vue'
import SubFunctions from '@/components/sub/SubFunctions.vue'
import SubMine from '@/components/sub/SubMine.vue'
// 页签下标顺序,与 Sub 组件 @switch-tab 抛出的数字一一对应
const TAB_ORDER = ['home', 'functions', 'mine']
const tabs = [
{ name: 'home', text: '首页', icon: 'house' },
{ name: 'functions', text: '功能', icon: 'table-cells' },
{ name: 'mine', text: '我的', icon: 'user' }
]
const slug = ref('')
const sub = ref(null)
const activeTab = ref('home')
const visited = ref({ home: true, functions: false, mine: false })
const headPad = mpHeadPad()
onLoad((options) => {
slug.value = options && options.slug ? options.slug : 'crm'
sub.value = getSubsystem(slug.value)
if (!sub.value) uni.reLaunch({ url: '/pages/nav/nav' })
})
function onTabChange(name) {
activeTab.value = name
if (!visited.value[name]) visited.value[name] = true
}
function switchByIndex(i) {
onTabChange(TAB_ORDER[i] || 'home')
}
function goBackNav() {
uni.navigateBack({ fail: () => uni.reLaunch({ url: '/pages/nav/nav' }) })
}
</script>
<style lang="scss" scoped>
@import '@/src/styles/page-common.scss';
.page {
display: flex;
flex-direction: column;
height: 100vh;
background: $color-bg-page;
overflow: hidden;
}
/* ============ 顶部标识条 ============ */
.hero {
flex-shrink: 0;
position: relative;
z-index: 0;
// H5 端 --status-bar-height 为 0,此时仅保留 32rpx 内边距
padding: calc(var(--status-bar-height, 44px) + 32rpx) $page-padding-x 72rpx;
}
.hero-back {
width: 56rpx;
height: 56rpx;
border-radius: 50%;
background: rgba(255, 255, 255, 0.22);
display: flex;
align-items: center;
justify-content: center;
transition: transform 0.15s ease;
&:active {
transform: scale(0.92);
}
}
.hero-main {
display: flex;
align-items: center;
gap: 22rpx;
margin-top: 28rpx;
}
.hero-icon {
width: 88rpx;
height: 88rpx;
border-radius: 26rpx;
background: rgba(255, 255, 255, 0.2);
border: 1rpx solid rgba(255, 255, 255, 0.32);
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
}
.hero-meta {
flex: 1;
min-width: 0;
display: flex;
flex-direction: column;
}
.hero-name {
font-size: 38rpx;
font-weight: 700;
letter-spacing: 1rpx;
color: #ffffff;
}
.hero-desc {
margin-top: 10rpx;
font-size: 22rpx;
line-height: 1.4;
color: rgba(255, 255, 255, 0.82);
}
/* ============ 内容区:上移压住渐变条,圆角衔接 ============ */
.content {
flex: 1;
min-height: 0;
position: relative;
z-index: 1;
margin-top: -44rpx;
border-radius: 32rpx 32rpx 0 0;
background: $color-bg-page;
overflow: hidden;
}
.pane {
height: 100%;
}
.pane-bottom {
height: 32rpx;
}
</style>