文件
shanghaipeiwan/pwuniapp/App.vue
xcbyy 8196b1925b feat(ui): 首页/雷达/TabBar 首版高级感视觉升级
- 扩展设计 Token:表面层级、发丝线、圆角、间距、动效曲线、数字字体

- 首页:克制霓虹背景、玻璃搜索栏、大图 Banner、金色标题、横向筛选胶囊、封面渐变、认证角标、卡片错峰入场、匹配弹窗改底部 Sheet

- 雷达:感知舱玻璃层级、细线同心圆、低干扰扫描、Marker 弹性落点、订单卡片左侧状态线、暖色主题适配

- TabBar:玻璃悬浮、选中指示条、中间发单按钮分层高光、暖色主题同步

- 已通过 HBuilderX 编译并生成预览二维码;777 用例全绿
2026-10-23 11:21:55 +08:00

437 行
14 KiB
Vue

此文件含有模棱两可的 Unicode 字符

此文件含有可能会与其他字符混淆的 Unicode 字符。 如果您是想特意这样的,可以安全地忽略该警告。 使用 Escape 按钮显示他们。

<script>
import { getCurrentThemeKey, applyThemeToNativeUI } from './common/theme.js';
import { installRoleGuard, getCurrentRole, ROLE_TYPES, isExpertCertified, safeRedirectToExpertHall } from './common/role.js';
export default {
onLaunch: function (options) {
// #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();
// 如果以大神身份冷启动或刷新进入首页根路径,自动平滑路由至大神接单大厅
try {
const launchPath = options && options.path;
if (!launchPath || launchPath === 'pages/index/index' || launchPath === '/pages/index/index') {
if (getCurrentRole() === ROLE_TYPES.EXPERT && isExpertCertified()) {
safeRedirectToExpertHall('/pages/expert/hall');
}
}
} catch (_) {}
// 注册全局路由切换拦截器,在跳转目标页面前预先同步 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;
}
/* 底部自定义 TabBar 全局兜底规范,锁死图标尺寸与定位,杜绝微信小程序中 image 标签退化为 320x240 默认尺寸 */
.custom-tabbar-root {
width: 100%;
.tabbar-container {
position: fixed !important;
bottom: 0 !important;
left: 0 !important;
right: 0 !important;
margin: 0 auto !important;
max-width: 450px !important;
box-sizing: border-box !important;
height: calc(118rpx + env(safe-area-inset-bottom)) !important;
display: flex !important;
align-items: flex-start !important;
justify-content: space-around !important;
z-index: 999 !important;
}
.tab-item {
flex: 1 !important;
display: flex !important;
flex-direction: column !important;
align-items: center !important;
justify-content: center !important;
height: 118rpx !important;
}
.tab-icon-svg {
width: 50rpx !important;
height: 50rpx !important;
max-width: 50rpx !important;
max-height: 50rpx !important;
flex-shrink: 0 !important;
}
.plus-circle-btn {
width: 96rpx !important;
height: 96rpx !important;
min-width: 96rpx !important;
min-height: 96rpx !important;
max-width: 96rpx !important;
max-height: 96rpx !important;
border-radius: 50% !important;
flex-shrink: 0 !important;
display: flex !important;
align-items: center !important;
justify-content: center !important;
.plus-svg {
width: 48rpx !important;
height: 48rpx !important;
flex-shrink: 0 !important;
}
}
.radar-icon-box {
width: 52rpx !important;
height: 52rpx !important;
.radar-svg {
width: 52rpx !important;
height: 52rpx !important;
flex-shrink: 0 !important;
}
}
}
/* 移动端与 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 */
/* ===== 高级感设计系统扩展(轻奢夜色 · 克制霓虹) ===== */
:root, page {
--surface-0: #070B14;
--surface-1: #0F1626;
--surface-2: #161F33;
--surface-3: #1E2942;
--hairline: rgba(255, 255, 255, 0.08);
--hairline-strong: rgba(255, 255, 255, 0.14);
--gold: #D9A441;
--emerald: #10B981;
--radius-sm: 12rpx;
--radius-md: 20rpx;
--radius-lg: 28rpx;
--radius-xl: 36rpx;
--sp-1: 8rpx;
--sp-2: 16rpx;
--sp-3: 24rpx;
--sp-4: 32rpx;
--sp-5: 48rpx;
--sp-6: 64rpx;
--motion-fast: 120ms;
--motion-base: 220ms;
--motion-slow: 360ms;
--ease-out: cubic-bezier(0.22, 0.61, 0.36, 1);
--ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);
--shadow-card: 0 12rpx 32rpx rgba(0, 0, 0, 0.26);
--shadow-float: 0 24rpx 60rpx rgba(0, 0, 0, 0.38);
--font-num: 'DIN Alternate', 'SF Pro Display', 'Helvetica Neue', monospace;
}
page:has(.theme-warm), page.theme-warm, .theme-warm {
--surface-0: #FDFBF7;
--surface-1: #FFFFFF;
--surface-2: #F8F5F0;
--surface-3: #F1ECE4;
--hairline: #F0ECE4;
--hairline-strong: #E7E5E4;
--gold: #C2410C;
--emerald: #059669;
--shadow-card: 0 12rpx 28rpx rgba(28, 25, 23, 0.06);
--shadow-float: 0 24rpx 56rpx rgba(28, 25, 23, 0.12);
}
</style>