323 行
10 KiB
Vue
323 行
10 KiB
Vue
<script>
|
||
import { getCurrentThemeKey, applyThemeToNativeUI } from './common/theme.js';
|
||
import { installRoleGuard } from './common/role.js';
|
||
|
||
export default {
|
||
onLaunch: function () {
|
||
// #ifdef H5
|
||
if (typeof window !== 'undefined' && window.addEventListener) {
|
||
window.addEventListener('unhandledrejection', (event) => {
|
||
const reason = event && event.reason;
|
||
const errMsg = reason && (reason.errMsg || reason.message || '');
|
||
if (
|
||
typeof errMsg === 'string' && (
|
||
errMsg.includes('setNavigationBarColor') ||
|
||
errMsg.includes('setTabBarStyle') ||
|
||
errMsg.includes('hideTabBar') ||
|
||
errMsg.includes('not tabBar page') ||
|
||
errMsg.includes('page not found')
|
||
)
|
||
) {
|
||
event.preventDefault();
|
||
}
|
||
});
|
||
}
|
||
// #endif
|
||
|
||
// #ifdef MP-WEIXIN
|
||
if (typeof wx !== 'undefined' && wx.onUnhandledRejection) {
|
||
wx.onUnhandledRejection((event) => {
|
||
const reason = event && event.reason;
|
||
const errMsg = (reason && (reason.errMsg || reason.message)) || (typeof reason === 'string' ? reason : '');
|
||
if (
|
||
typeof errMsg === 'string' && (
|
||
errMsg.includes('hideTabBar') ||
|
||
errMsg.includes('not TabBar page') ||
|
||
errMsg.includes('setNavigationBarColor') ||
|
||
errMsg.includes('setTabBarStyle')
|
||
)
|
||
) {
|
||
// 自定义 TabBar 场景下,对非原生 TabBar 页面尝试隐藏 TabBar 的报错静默兜底
|
||
return;
|
||
}
|
||
});
|
||
}
|
||
// #endif
|
||
|
||
const currentTheme = getCurrentThemeKey();
|
||
applyThemeToNativeUI(currentTheme);
|
||
|
||
// 注册全流程角色权限守卫拦截器 (Role Guard)
|
||
installRoleGuard();
|
||
|
||
// 注册全局路由切换拦截器,在跳转目标页面前预先同步 Native 导航栏与窗口背景,消除切页黑屏闪烁
|
||
const routeMethods = ['navigateTo', 'redirectTo', 'reLaunch', 'switchTab'];
|
||
routeMethods.forEach((method) => {
|
||
try {
|
||
if (typeof uni !== 'undefined' && typeof uni.addInterceptor === 'function') {
|
||
uni.addInterceptor(method, {
|
||
invoke() {
|
||
applyThemeToNativeUI(getCurrentThemeKey());
|
||
}
|
||
});
|
||
}
|
||
} catch (e) {}
|
||
});
|
||
|
||
console.log('App Launch: 电竞陪玩小程序初始化, 当前主题:', currentTheme);
|
||
},
|
||
onShow: function () {
|
||
const currentTheme = getCurrentThemeKey();
|
||
applyThemeToNativeUI(currentTheme);
|
||
},
|
||
onHide: function () {
|
||
console.log('App Hide');
|
||
},
|
||
};
|
||
</script>
|
||
|
||
<style lang="scss">
|
||
/* 双主题 Design Tokens (CSS Variables 全局动态驱动) */
|
||
:root, page {
|
||
--bg-primary: #0A0F1D;
|
||
--bg-surface: #151D30;
|
||
--bg-surface-elevated: #1E2942;
|
||
--bg-surface-glass: rgba(21, 29, 48, 0.85);
|
||
--color-brand: #6366F1;
|
||
--color-brand-light: #818CF8;
|
||
--color-brand-gold: #F59E0B;
|
||
--color-brand-glow: rgba(99, 102, 241, 0.35);
|
||
--color-brand-gradient: linear-gradient(135deg, #6366F1, #8B5CF6);
|
||
--border-subtle: #1E293B;
|
||
--border-focus: #4F46E5;
|
||
--text-primary: #F8FAFC;
|
||
--text-secondary: #94A3B8;
|
||
--text-muted: #64748B;
|
||
--shadow-brand: 0 8rpx 24rpx rgba(99, 102, 241, 0.35);
|
||
--nav-bg: #0A0F1D;
|
||
--nav-color: #F8FAFC;
|
||
--tab-bg: #151D30;
|
||
--tab-color: #94A3B8;
|
||
--tab-active: #6366F1;
|
||
|
||
/* 顶部与多端安全区变量 (小程序状态栏 / 原生胶囊避让 / H5 沉浸式自然留白) */
|
||
--safe-header-gap: calc(var(--status-bar-height, 0px) + 36rpx);
|
||
--capsule-right-space: 0rpx;
|
||
--capsule-height: 72rpx;
|
||
|
||
/* #ifdef MP-WEIXIN */
|
||
/* 微信小程序端静态 CSS 兜底:状态栏加上胶囊行对齐留白 (避开灵动岛与状态栏遮挡) */
|
||
--safe-header-gap: calc(var(--status-bar-height, 25px) + 58rpx);
|
||
--capsule-right-space: 210rpx;
|
||
--capsule-height: 64rpx;
|
||
/* #endif */
|
||
}
|
||
|
||
/* 浅色暖阳晨曦主题 (Light Warm Sunset Morning) */
|
||
page:has(.theme-warm), page.theme-warm, .theme-warm {
|
||
--bg-primary: #FDFBF7;
|
||
--bg-surface: #FFFFFF;
|
||
--bg-surface-elevated: #F8F5F0;
|
||
--bg-surface-glass: rgba(255, 255, 255, 0.90);
|
||
--color-brand: #EA580C;
|
||
--color-brand-light: #F97316;
|
||
--color-brand-gold: #F59E0B;
|
||
--color-brand-glow: rgba(234, 88, 12, 0.18);
|
||
--color-brand-gradient: linear-gradient(135deg, #F97316, #FB923C);
|
||
--border-subtle: #F0ECE4;
|
||
--border-focus: #EA580C;
|
||
--text-primary: #1C1917;
|
||
--text-secondary: #57534E;
|
||
--text-muted: #78716C;
|
||
--shadow-brand: 0 8rpx 24rpx rgba(234, 88, 12, 0.25);
|
||
--nav-bg: #FDFBF7;
|
||
--nav-color: #1C1917;
|
||
--tab-bg: #FFFFFF;
|
||
--tab-color: #78716C;
|
||
--tab-active: #EA580C;
|
||
|
||
background-color: #FDFBF7;
|
||
color: #1C1917;
|
||
}
|
||
|
||
page:has(.theme-warm) {
|
||
background-color: #FDFBF7 !important;
|
||
}
|
||
|
||
/* 全局暗黑电竞基础重置 (严格符合 UI/UX Pro Max 规范) */
|
||
page {
|
||
background-color: var(--bg-primary, #0A0F1D);
|
||
color: var(--text-primary, #F8FAFC);
|
||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, 'PingFang SC', sans-serif;
|
||
box-sizing: border-box;
|
||
-webkit-font-smoothing: antialiased;
|
||
-webkit-tap-highlight-color: transparent;
|
||
}
|
||
|
||
view, text, image, input, button {
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
/* 触控交互微反馈:80-120ms 弹性缩放,无布局位移 (CLS < 0.1) */
|
||
.btn-active:active, .card-active:active {
|
||
transform: scale(0.975);
|
||
opacity: 0.88;
|
||
transition: transform 100ms cubic-bezier(0.2, 0.8, 0.2, 1), opacity 100ms ease-out;
|
||
}
|
||
|
||
/* 纯数字等宽排版 (避免金额、核销码、倒计时跳动) */
|
||
.tabular-num {
|
||
font-variant-numeric: tabular-nums;
|
||
font-feature-settings: "tnum";
|
||
}
|
||
|
||
/* 隐藏移动端原生滚动条 */
|
||
::-webkit-scrollbar {
|
||
display: none;
|
||
width: 0;
|
||
height: 0;
|
||
color: transparent;
|
||
}
|
||
|
||
/* 移动端与 H5 响应式体验优化 */
|
||
/* #ifdef H5 */
|
||
html, body {
|
||
background-color: #0A0F1D;
|
||
margin: 0;
|
||
padding: 0;
|
||
-webkit-tap-highlight-color: transparent;
|
||
touch-action: manipulation;
|
||
}
|
||
|
||
/* 在 PC 宽屏上以 iPhone 15 Pro 仿真机壳居中展示,兼顾专业质感 */
|
||
@media screen and (min-width: 481px) {
|
||
html, body {
|
||
background-color: #050811 !important;
|
||
transition: background-color 0.3s ease;
|
||
}
|
||
|
||
body:has(.theme-warm) {
|
||
background-color: #EDE8E0 !important;
|
||
}
|
||
|
||
uni-app {
|
||
max-width: 450px !important;
|
||
margin: 20px auto !important;
|
||
min-height: calc(100vh - 40px) !important;
|
||
box-shadow: 0 0 60rpx rgba(0, 0, 0, 0.4), 0 0 0 2rpx var(--color-brand-glow, rgba(99, 102, 241, 0.25)) !important;
|
||
border-radius: 40rpx !important;
|
||
overflow: hidden !important;
|
||
position: relative !important;
|
||
background-color: var(--bg-primary, #0A0F1D) !important;
|
||
}
|
||
|
||
uni-page-head, .uni-page-head {
|
||
max-width: 450px !important;
|
||
left: 0 !important;
|
||
right: 0 !important;
|
||
margin: 0 auto !important;
|
||
top: 20px !important;
|
||
border-top-left-radius: 40rpx !important;
|
||
border-top-right-radius: 40rpx !important;
|
||
overflow: hidden !important;
|
||
}
|
||
|
||
uni-tabbar, .uni-tabbar {
|
||
position: fixed !important;
|
||
bottom: 20px !important;
|
||
left: 0 !important;
|
||
right: 0 !important;
|
||
margin: 0 auto !important;
|
||
max-width: 450px !important;
|
||
width: 100% !important;
|
||
z-index: 9999 !important;
|
||
border-bottom-left-radius: 40rpx !important;
|
||
border-bottom-right-radius: 40rpx !important;
|
||
overflow: hidden !important;
|
||
}
|
||
}
|
||
|
||
/* 在手机移动浏览器上 100% 原生沉浸贴合,适配动态视口与底部安全区 */
|
||
@media screen and (max-width: 480px) {
|
||
uni-app {
|
||
width: 100% !important;
|
||
min-height: 100vh !important;
|
||
min-height: 100dvh !important;
|
||
}
|
||
|
||
uni-tabbar, .uni-tabbar {
|
||
position: fixed !important;
|
||
bottom: 0 !important;
|
||
left: 0 !important;
|
||
right: 0 !important;
|
||
width: 100% !important;
|
||
z-index: 9999 !important;
|
||
padding-bottom: env(safe-area-inset-bottom) !important;
|
||
}
|
||
}
|
||
|
||
uni-tabbar .uni-tabbar__bd {
|
||
background-color: var(--tab-bg, var(--bg-surface, #151D30)) !important;
|
||
border-top: 1px solid var(--border-subtle, rgba(255, 255, 255, 0.08)) !important;
|
||
transition: background-color 0.2s ease;
|
||
}
|
||
|
||
/* 顶部导航栏 (H5 端 uni-page-head 动态浅色/暗黑主题自适应) */
|
||
uni-page-head, .uni-page-head {
|
||
background-color: var(--nav-bg, var(--bg-primary, #0A0F1D)) !important;
|
||
color: var(--nav-color, var(--text-primary, #F8FAFC)) !important;
|
||
border-bottom: 1px solid var(--border-subtle, rgba(255, 255, 255, 0.08)) !important;
|
||
transition: background-color 0.2s ease, color 0.2s ease;
|
||
}
|
||
|
||
uni-page-head .uni-page-head__title {
|
||
color: var(--nav-color, var(--text-primary, #F8FAFC)) !important;
|
||
}
|
||
|
||
/* 浅色暖阳晨曦模式下强制确保 TabBar 与 PageHead 呈现高质感浅色 */
|
||
body:has(.theme-warm) uni-page-head,
|
||
body:has(.theme-warm) .uni-page-head,
|
||
page.theme-warm ~ uni-page-head,
|
||
.theme-warm uni-page-head {
|
||
background-color: #FDFBF7 !important;
|
||
border-bottom: 1px solid #F0ECE4 !important;
|
||
}
|
||
|
||
body:has(.theme-warm) uni-page-head .uni-page-head__title,
|
||
body:has(.theme-warm) .uni-page-head .uni-page-head__title,
|
||
page.theme-warm ~ uni-page-head .uni-page-head__title,
|
||
.theme-warm uni-page-head .uni-page-head__title,
|
||
body:has(.theme-warm) uni-page-head *,
|
||
.theme-warm uni-page-head * {
|
||
color: #1C1917 !important;
|
||
}
|
||
|
||
body:has(.theme-warm) uni-tabbar .uni-tabbar__bd,
|
||
page.theme-warm ~ uni-tabbar .uni-tabbar__bd,
|
||
.theme-warm ~ uni-tabbar .uni-tabbar__bd {
|
||
background-color: #FFFFFF !important;
|
||
border-top: 1px solid #F0ECE4 !important;
|
||
box-shadow: 0 -4rpx 20rpx rgba(28, 25, 23, 0.04) !important;
|
||
}
|
||
|
||
body:has(.theme-warm) uni-tabbar .uni-tabbar__label,
|
||
page.theme-warm ~ uni-tabbar .uni-tabbar__label,
|
||
body:has(.theme-warm) uni-tabbar span {
|
||
color: #78716C !important;
|
||
font-size: 13px !important;
|
||
font-weight: 500 !important;
|
||
}
|
||
|
||
body:has(.theme-warm) uni-tabbar .uni-tabbar-item.active .uni-tabbar__label,
|
||
page.theme-warm ~ uni-tabbar .uni-tabbar-item.active .uni-tabbar__label,
|
||
body:has(.theme-warm) uni-tabbar .uni-tabbar__item.active .uni-tabbar__label,
|
||
page.theme-warm ~ uni-tabbar .uni-tabbar__item.active .uni-tabbar__label,
|
||
body:has(.theme-warm) uni-tabbar .active .uni-tabbar__label,
|
||
body:has(.theme-warm) uni-tabbar [class*="active"] .uni-tabbar__label,
|
||
body:has(.theme-warm) uni-tabbar [class*="active"] span {
|
||
color: #EA580C !important;
|
||
font-weight: 700 !important;
|
||
}
|
||
/* #endif */
|
||
</style>
|