Files
EmailBill/Web/src/App.vue
孙诚 da227d13ea
All checks were successful
Docker Build & Deploy / Build Docker Image (push) Successful in 14s
Docker Build & Deploy / Deploy to Production (push) Successful in 6s
debugger
2025-12-25 17:28:06 +08:00

154 lines
4.1 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>
<van-config-provider :theme="theme" class="app-provider">
<pre style="position:fixed; left:0; top:0; z-index:9999;
background:rgba(0,0,0,0.7); color:#0f0;
font-size:10px; max-height:50vh; overflow:auto;">
{{ log }}
</pre>
<div class="app-root">
<RouterView />
<van-tabbar v-model="active" v-show="showTabbar">
<van-tabbar-item icon="notes-o" to="/calendar">
日历
</van-tabbar-item>
<van-tabbar-item icon="balance-list-o" to="/" @click="handleTabClick('/')">
账单
</van-tabbar-item>
<van-tabbar-item icon="records-o" to="/email" @click="handleTabClick('/email')">
邮件
</van-tabbar-item>
<van-tabbar-item icon="setting-o" to="/setting">
设置
</van-tabbar-item>
</van-tabbar>
</div>
</van-config-provider>
</template>
<script setup>
import { RouterView, useRoute } from 'vue-router'
import { ref, onMounted, onUnmounted, computed } from 'vue'
const log = ref('')
const updateInfo = () => {
// 获取真实的视口高度PWA 模式下准确)
const vh = window.innerHeight
const safeAreaBottom = getComputedStyle(document.documentElement).getPropertyValue('padding-bottom')
// 设置 CSS 变量,让所有组件使用准确的视口高度
document.documentElement.style.setProperty('--vh', `${vh}px`)
document.documentElement.style.setProperty('--vh-offset', `${vh}px`)
// 获取 TabBar 的实际高度
const tabbar = document.querySelector('.van-tabbar')
const tabbarHeight = tabbar ? tabbar.offsetHeight : 0
log.value = JSON.stringify({
innerHeight: window.innerHeight,
outerHeight: window.outerHeight,
documentElementClientHeight: document.documentElement.clientHeight,
viewport: window.visualViewport
? {
height: window.visualViewport.height,
offsetTop: window.visualViewport.offsetTop,
}
: null,
cssVarVh: getComputedStyle(document.documentElement).getPropertyValue('--vh'),
tabbarHeight: tabbarHeight,
safeAreaInsetBottom: safeAreaBottom,
computedSpace: `${vh} - ${tabbarHeight} = ${vh - tabbarHeight}px`,
}, null, 2)
}
onMounted(() => {
updateInfo()
window.addEventListener('resize', updateInfo)
// 监听 iOS Safari 视口变化
if (window.visualViewport) {
window.visualViewport.addEventListener('resize', updateInfo)
}
})
onUnmounted(() => {
window.removeEventListener('resize', updateInfo)
if (window.visualViewport) {
window.visualViewport.removeEventListener('resize', updateInfo)
}
})
const route = useRoute()
// 根据路由判断是否显示Tabbar
const showTabbar = computed(() => {
return route.path === '/' ||
route.path === '/calendar' ||
route.path === '/email' ||
route.path === '/setting'
})
const active = ref(0)
const theme = ref('light')
// 检测系统深色模式
const updateTheme = () => {
const isDark = window.matchMedia('(prefers-color-scheme: dark)').matches
theme.value = isDark ? 'dark' : 'light'
}
// 监听系统主题变化
let mediaQuery
onMounted(() => {
updateTheme()
mediaQuery = window.matchMedia('(prefers-color-scheme: dark)')
mediaQuery.addEventListener('change', updateTheme)
})
onUnmounted(() => {
if (mediaQuery) {
mediaQuery.removeEventListener('change', updateTheme)
}
})
// 处理tab点击如果点击当前页面则滚动到顶部
const handleTabClick = (path) => {
if (route.path === path) {
window.scrollTo({ top: 0, behavior: 'smooth' })
}
}
</script>
<style scoped>
.app-provider {
/* 使用准确的视口高度 CSS 变量 */
height: var(--vh, 100vh);
width: 100%;
}
.app-root {
height: 100%;
width: 100%;
position: relative;
border: 2px solid red; /* 调试用红框 */
}
/* TabBar 固定在底部 */
:deep(.van-tabbar) {
position: fixed !important;
bottom: 0 !important;
left: 0;
right: 0;
/* 重置所有 padding然后只添加安全区域 */
padding: 0 !important;
padding-bottom: env(safe-area-inset-bottom, 0px) !important;
height: 50px !important;
min-height: 50px !important;
}
/* 确保 TabBar 项目居中 */
:deep(.van-tabbar-item) {
padding: 0 !important;
}
</style>