PWA支持
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<van-config-provider :theme="theme">
|
||||
<RouterView />
|
||||
<van-tabbar v-model="active" v-show="showTabbar">
|
||||
<van-tabbar v-model="active" v-show="showTabbar" safe-area-inset-bottom>
|
||||
<van-tabbar-item icon="notes-o" to="/calendar">
|
||||
日历
|
||||
</van-tabbar-item>
|
||||
@@ -61,3 +61,19 @@ const handleTabClick = (path) => {
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* 为 Tabbar 添加额外的底部安全区域适配 */
|
||||
:deep(.van-tabbar) {
|
||||
padding-bottom: constant(safe-area-inset-bottom);
|
||||
padding-bottom: env(safe-area-inset-bottom);
|
||||
/* 在原有高度基础上增加安全区域 */
|
||||
height: calc(50px + constant(safe-area-inset-bottom));
|
||||
height: calc(50px + env(safe-area-inset-bottom));
|
||||
}
|
||||
|
||||
/* 确保内容不被 Tabbar 遮挡 */
|
||||
:deep(.van-tabbar) + * {
|
||||
padding-bottom: constant(safe-area-inset-bottom);
|
||||
padding-bottom: env(safe-area-inset-bottom);
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,9 +1,35 @@
|
||||
@import './base.css';
|
||||
|
||||
/* 禁用页面弹性缩放和橡皮筋效果 */
|
||||
html, body {
|
||||
overscroll-behavior: none;
|
||||
overscroll-behavior-y: none;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
touch-action: pan-y;
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
body {
|
||||
-webkit-user-select: none;
|
||||
-webkit-touch-callout: none;
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
}
|
||||
|
||||
#app {
|
||||
max-width: 1280px;
|
||||
margin: 0 auto;
|
||||
font-weight: normal;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
|
||||
a,
|
||||
|
||||
@@ -9,6 +9,9 @@ import vant from 'vant'
|
||||
import { ConfigProvider } from 'vant';
|
||||
import 'vant/lib/index.css'
|
||||
|
||||
// 注册 Service Worker
|
||||
import { register } from './registerServiceWorker'
|
||||
|
||||
const app = createApp(App)
|
||||
|
||||
app.use(createPinia())
|
||||
@@ -17,3 +20,8 @@ app.use(vant)
|
||||
app.use(ConfigProvider);
|
||||
|
||||
app.mount('#app')
|
||||
|
||||
// 在生产环境注册 Service Worker
|
||||
if (import.meta.env.PROD) {
|
||||
register()
|
||||
}
|
||||
|
||||
92
Web/src/registerServiceWorker.js
Normal file
92
Web/src/registerServiceWorker.js
Normal file
@@ -0,0 +1,92 @@
|
||||
/* eslint-disable no-console */
|
||||
|
||||
export function register() {
|
||||
if ('serviceWorker' in navigator) {
|
||||
window.addEventListener('load', () => {
|
||||
const swUrl = `/service-worker.js`;
|
||||
|
||||
navigator.serviceWorker
|
||||
.register(swUrl)
|
||||
.then((registration) => {
|
||||
console.log('[SW] Service Worker 注册成功:', registration.scope);
|
||||
|
||||
// 检查更新
|
||||
registration.addEventListener('updatefound', () => {
|
||||
const newWorker = registration.installing;
|
||||
console.log('[SW] 发现新版本');
|
||||
|
||||
newWorker.addEventListener('statechange', () => {
|
||||
if (newWorker.state === 'installed') {
|
||||
if (navigator.serviceWorker.controller) {
|
||||
// 新的 Service Worker 已安装,提示用户刷新
|
||||
console.log('[SW] 新版本可用,请刷新页面');
|
||||
showUpdateNotification();
|
||||
} else {
|
||||
// 首次安装
|
||||
console.log('[SW] 内容已缓存,可离线使用');
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// 定期检查更新
|
||||
setInterval(() => {
|
||||
registration.update();
|
||||
}, 60 * 60 * 1000); // 每小时检查一次
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('[SW] Service Worker 注册失败:', error);
|
||||
});
|
||||
|
||||
// 监听 Service Worker 控制器变化
|
||||
navigator.serviceWorker.addEventListener('controllerchange', () => {
|
||||
console.log('[SW] 控制器已更改,页面将刷新');
|
||||
window.location.reload();
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export function unregister() {
|
||||
if ('serviceWorker' in navigator) {
|
||||
navigator.serviceWorker.ready
|
||||
.then((registration) => {
|
||||
registration.unregister();
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error(error.message);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 显示更新提示
|
||||
function showUpdateNotification() {
|
||||
// 你可以使用 Vant 的 Dialog 或 Notify 组件
|
||||
if (window.confirm('发现新版本,是否立即更新?')) {
|
||||
window.location.reload();
|
||||
}
|
||||
}
|
||||
|
||||
// 请求通知权限
|
||||
export function requestNotificationPermission() {
|
||||
if ('Notification' in window && 'serviceWorker' in navigator) {
|
||||
Notification.requestPermission().then((permission) => {
|
||||
if (permission === 'granted') {
|
||||
console.log('[SW] 通知权限已授予');
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 后台同步
|
||||
export function registerBackgroundSync(tag = 'sync-data') {
|
||||
if ('serviceWorker' in navigator && 'SyncManager' in window) {
|
||||
navigator.serviceWorker.ready.then((registration) => {
|
||||
return registration.sync.register(tag);
|
||||
}).then(() => {
|
||||
console.log('[SW] 后台同步已注册:', tag);
|
||||
}).catch((err) => {
|
||||
console.error('[SW] 后台同步注册失败:', err);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -53,7 +53,7 @@ const handleLogin = async () => {
|
||||
try {
|
||||
await authStore.login(password.value)
|
||||
showToast({ type: 'success', message: '登录成功' })
|
||||
router.push('/')
|
||||
router.push('/calendar')
|
||||
} catch (error) {
|
||||
showToast({ type: 'fail', message: error.message || '登录失败' })
|
||||
} finally {
|
||||
|
||||
Reference in New Issue
Block a user