feat(theme): 完善顶部导航栏与底部菜单浅色暖色系适配及多端Tab生命周期同步
这个提交包含在:
@@ -1,13 +1,15 @@
|
||||
<script>
|
||||
import { getCurrentThemeKey } from './common/theme.js';
|
||||
import { getCurrentThemeKey, applyThemeToNativeUI } from './common/theme.js';
|
||||
|
||||
export default {
|
||||
onLaunch: function () {
|
||||
const currentTheme = getCurrentThemeKey();
|
||||
applyThemeToNativeUI(currentTheme);
|
||||
console.log('App Launch: 电竞陪玩小程序初始化, 当前主题:', currentTheme);
|
||||
},
|
||||
onShow: function () {
|
||||
console.log('App Show');
|
||||
const currentTheme = getCurrentThemeKey();
|
||||
applyThemeToNativeUI(currentTheme);
|
||||
},
|
||||
onHide: function () {
|
||||
console.log('App Hide');
|
||||
@@ -33,6 +35,11 @@ export default {
|
||||
--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;
|
||||
}
|
||||
|
||||
/* 浅色暖阳晨曦主题 (Light Warm Sunset Morning) */
|
||||
@@ -52,6 +59,11 @@ page.theme-warm, .theme-warm {
|
||||
--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;
|
||||
@@ -161,8 +173,52 @@ html, body {
|
||||
}
|
||||
|
||||
uni-tabbar .uni-tabbar__bd {
|
||||
background-color: var(--bg-surface, #151D30) !important;
|
||||
border-top: 1px solid rgba(255, 255, 255, 0.08) !important;
|
||||
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,
|
||||
page.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,
|
||||
page.theme-warm ~ uni-page-head .uni-page-head__title {
|
||||
color: #1C1917 !important;
|
||||
}
|
||||
|
||||
body:has(.theme-warm) uni-tabbar .uni-tabbar__bd,
|
||||
page.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 {
|
||||
color: #78716C !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 {
|
||||
color: #EA580C !important;
|
||||
}
|
||||
/* #endif */
|
||||
</style>
|
||||
|
||||
@@ -28,7 +28,17 @@ export const THEMES = {
|
||||
textPrimary: '#F8FAFC',
|
||||
textSecondary: '#94A3B8',
|
||||
textMuted: '#64748B',
|
||||
shadowBrand: '0 8rpx 24rpx rgba(99, 102, 241, 0.35)'
|
||||
shadowBrand: '0 8rpx 24rpx rgba(99, 102, 241, 0.35)',
|
||||
navBar: {
|
||||
backgroundColor: '#0A0F1D',
|
||||
frontColor: '#ffffff'
|
||||
},
|
||||
tabBar: {
|
||||
color: '#94A3B8',
|
||||
selectedColor: '#6366F1',
|
||||
backgroundColor: '#151D30',
|
||||
borderStyle: 'black'
|
||||
}
|
||||
}
|
||||
},
|
||||
[THEME_KEYS.WARM]: {
|
||||
@@ -50,13 +60,61 @@ export const THEMES = {
|
||||
textPrimary: '#1C1917',
|
||||
textSecondary: '#57534E',
|
||||
textMuted: '#78716C',
|
||||
shadowBrand: '0 8rpx 24rpx rgba(234, 88, 12, 0.25)'
|
||||
shadowBrand: '0 8rpx 24rpx rgba(234, 88, 12, 0.25)',
|
||||
navBar: {
|
||||
backgroundColor: '#FDFBF7',
|
||||
frontColor: '#000000'
|
||||
},
|
||||
tabBar: {
|
||||
color: '#78716C',
|
||||
selectedColor: '#EA580C',
|
||||
backgroundColor: '#FFFFFF',
|
||||
borderStyle: 'white'
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const STORAGE_KEY = 'peiwan_app_theme';
|
||||
|
||||
/**
|
||||
* 将主题色彩同步应用至小程序与原生顶部导航栏及底部 TabBar
|
||||
*/
|
||||
export function applyThemeToNativeUI(themeKey) {
|
||||
const theme = THEMES[themeKey] || THEMES[THEME_KEYS.COOL];
|
||||
const { navBar, tabBar } = theme.tokens;
|
||||
|
||||
// 1. 设置顶部系统导航栏颜色
|
||||
try {
|
||||
if (typeof uni !== 'undefined' && uni.setNavigationBarColor) {
|
||||
uni.setNavigationBarColor({
|
||||
frontColor: navBar.frontColor,
|
||||
backgroundColor: navBar.backgroundColor,
|
||||
animation: {
|
||||
duration: 200,
|
||||
timingFunc: 'easeOut'
|
||||
}
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
// 忽略特定页面无系统导航栏异常
|
||||
}
|
||||
|
||||
// 2. 设置底部原生 TabBar 菜单颜色
|
||||
try {
|
||||
if (typeof uni !== 'undefined' && uni.setTabBarStyle) {
|
||||
uni.setTabBarStyle({
|
||||
color: tabBar.color,
|
||||
selectedColor: tabBar.selectedColor,
|
||||
backgroundColor: tabBar.backgroundColor,
|
||||
borderStyle: tabBar.borderStyle
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
// 忽略非 TabBar 页面抛出的异常
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前持久化的主题标识
|
||||
*/
|
||||
@@ -88,7 +146,7 @@ export function getCurrentTokens() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 切换全局主题并持久化,广播全局事件
|
||||
* 切换全局主题并持久化,广播全局事件,同步更新顶部与底部 UI
|
||||
*/
|
||||
export function setTheme(themeKey) {
|
||||
const targetKey = THEMES[themeKey] ? themeKey : THEME_KEYS.COOL;
|
||||
@@ -97,6 +155,9 @@ export function setTheme(themeKey) {
|
||||
} catch (e) {
|
||||
// 忽略持久化异常
|
||||
}
|
||||
|
||||
// 同步原生顶部与底部栏色彩
|
||||
applyThemeToNativeUI(targetKey);
|
||||
|
||||
// 广播主题变更事件
|
||||
try {
|
||||
|
||||
@@ -153,9 +153,10 @@
|
||||
|
||||
<script setup>
|
||||
import { ref, computed, onMounted, onUnmounted } from 'vue';
|
||||
import { onShow } from '@dcloudio/uni-app';
|
||||
import { ACTIVITIES_LIST } from '@/common/mock.js';
|
||||
import { ICONS } from '@/common/icons.js';
|
||||
import { getCurrentThemeKey } from '@/common/theme.js';
|
||||
import { getCurrentThemeKey, applyThemeToNativeUI } from '@/common/theme.js';
|
||||
|
||||
const activities = ref(ACTIVITIES_LIST);
|
||||
const currentTab = ref('ALL');
|
||||
@@ -164,6 +165,7 @@ const currentThemeKey = ref(getCurrentThemeKey());
|
||||
|
||||
const onThemeChanged = (key) => {
|
||||
currentThemeKey.value = key;
|
||||
applyThemeToNativeUI(key);
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
@@ -171,6 +173,11 @@ onMounted(() => {
|
||||
uni.$on('theme-change', onThemeChanged);
|
||||
});
|
||||
|
||||
onShow(() => {
|
||||
currentThemeKey.value = getCurrentThemeKey();
|
||||
applyThemeToNativeUI(currentThemeKey.value);
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
uni.$off('theme-change', onThemeChanged);
|
||||
});
|
||||
|
||||
@@ -143,9 +143,10 @@
|
||||
|
||||
<script setup>
|
||||
import { ref, computed, onMounted, onUnmounted } from 'vue';
|
||||
import { onShow } from '@dcloudio/uni-app';
|
||||
import { GAMES_LIST, BANNERS, EXPERTS_LIST } from '@/common/mock.js';
|
||||
import { ICONS } from '@/common/icons.js';
|
||||
import { getCurrentThemeKey } from '@/common/theme.js';
|
||||
import { getCurrentThemeKey, applyThemeToNativeUI } from '@/common/theme.js';
|
||||
|
||||
const games = ref(GAMES_LIST);
|
||||
const banners = ref(BANNERS);
|
||||
@@ -156,13 +157,20 @@ const currentThemeKey = ref(getCurrentThemeKey());
|
||||
|
||||
const onThemeChanged = (key) => {
|
||||
currentThemeKey.value = key;
|
||||
applyThemeToNativeUI(key);
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
currentThemeKey.value = getCurrentThemeKey();
|
||||
applyThemeToNativeUI(currentThemeKey.value);
|
||||
uni.$on('theme-change', onThemeChanged);
|
||||
});
|
||||
|
||||
onShow(() => {
|
||||
currentThemeKey.value = getCurrentThemeKey();
|
||||
applyThemeToNativeUI(currentThemeKey.value);
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
uni.$off('theme-change', onThemeChanged);
|
||||
});
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<view class="order-list-container">
|
||||
<view class="order-list-container" :class="{ 'theme-warm': currentThemeKey === 'warm' }">
|
||||
<!-- 顶部状态分类 Tab -->
|
||||
<view class="tab-header">
|
||||
<view
|
||||
@@ -76,9 +76,32 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, computed } from 'vue';
|
||||
import { ref, computed, onMounted, onUnmounted } from 'vue';
|
||||
import { onShow } from '@dcloudio/uni-app';
|
||||
import { ORDERS_LIST } from '@/common/mock.js';
|
||||
import { ICONS } from '@/common/icons.js';
|
||||
import { getCurrentThemeKey, applyThemeToNativeUI } from '@/common/theme.js';
|
||||
|
||||
const currentThemeKey = ref(getCurrentThemeKey());
|
||||
|
||||
const onThemeChanged = (key) => {
|
||||
currentThemeKey.value = key;
|
||||
applyThemeToNativeUI(key);
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
currentThemeKey.value = getCurrentThemeKey();
|
||||
uni.$on('theme-change', onThemeChanged);
|
||||
});
|
||||
|
||||
onShow(() => {
|
||||
currentThemeKey.value = getCurrentThemeKey();
|
||||
applyThemeToNativeUI(currentThemeKey.value);
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
uni.$off('theme-change', onThemeChanged);
|
||||
});
|
||||
|
||||
const tabs = [
|
||||
{ key: 'ALL', name: '全部' },
|
||||
@@ -435,4 +458,89 @@ const rateExpert = (id) => {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.order-list-container.theme-warm {
|
||||
background-color: #FDFBF7;
|
||||
|
||||
.tab-header {
|
||||
background-color: #FFFFFF;
|
||||
border-color: #F0ECE4;
|
||||
box-shadow: 0 4rpx 16rpx rgba(28, 25, 23, 0.04);
|
||||
|
||||
.tab-item {
|
||||
.tab-text {
|
||||
color: #78716C;
|
||||
}
|
||||
&.active {
|
||||
background: rgba(234, 88, 12, 0.1);
|
||||
.tab-text {
|
||||
color: #EA580C;
|
||||
}
|
||||
.tab-indicator {
|
||||
background: #EA580C;
|
||||
box-shadow: 0 0 10rpx rgba(234, 88, 12, 0.4);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.orders-wrap .order-card {
|
||||
background-color: #FFFFFF;
|
||||
border-color: #F0ECE4;
|
||||
box-shadow: 0 6rpx 20rpx rgba(28, 25, 23, 0.05);
|
||||
|
||||
.order-head {
|
||||
border-bottom-color: #F5F2EC;
|
||||
.order-sn {
|
||||
color: #78716C;
|
||||
}
|
||||
}
|
||||
|
||||
.expert-block {
|
||||
.expert-meta {
|
||||
.name-row .expert-name {
|
||||
color: #1C1917;
|
||||
}
|
||||
.service-name {
|
||||
color: #57534E;
|
||||
}
|
||||
.order-time {
|
||||
color: #78716C;
|
||||
}
|
||||
}
|
||||
.amount-box .quantity-text {
|
||||
color: #78716C;
|
||||
}
|
||||
}
|
||||
|
||||
.order-actions {
|
||||
border-top-color: #F5F2EC;
|
||||
|
||||
.action-btn {
|
||||
&.cancel-btn {
|
||||
color: #78716C;
|
||||
border-color: #E7E5E4;
|
||||
}
|
||||
&.primary-btn {
|
||||
background: linear-gradient(135deg, #F97316 0%, #EA580C 100%);
|
||||
}
|
||||
&.chat-btn {
|
||||
background: rgba(234, 88, 12, 0.1);
|
||||
color: #EA580C;
|
||||
border-color: rgba(234, 88, 12, 0.25);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.empty-state {
|
||||
.empty-text {
|
||||
color: #78716C;
|
||||
}
|
||||
.empty-btn {
|
||||
background: linear-gradient(135deg, #F97316 0%, #EA580C 100%);
|
||||
box-shadow: 0 4rpx 16rpx rgba(234, 88, 12, 0.35);
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -121,9 +121,10 @@
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted, onUnmounted } from 'vue';
|
||||
import { onShow } from '@dcloudio/uni-app';
|
||||
import { USER_PROFILE } from '@/common/mock.js';
|
||||
import { ICONS } from '@/common/icons.js';
|
||||
import { getCurrentThemeKey, setTheme, THEME_KEYS } from '@/common/theme.js';
|
||||
import { getCurrentThemeKey, setTheme, THEME_KEYS, applyThemeToNativeUI } from '@/common/theme.js';
|
||||
|
||||
const user = ref(USER_PROFILE);
|
||||
const currentRole = ref('PLAYER');
|
||||
@@ -131,13 +132,20 @@ const currentThemeKey = ref(getCurrentThemeKey());
|
||||
|
||||
const onThemeChanged = (key) => {
|
||||
currentThemeKey.value = key;
|
||||
applyThemeToNativeUI(key);
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
currentThemeKey.value = getCurrentThemeKey();
|
||||
applyThemeToNativeUI(currentThemeKey.value);
|
||||
uni.$on('theme-change', onThemeChanged);
|
||||
});
|
||||
|
||||
onShow(() => {
|
||||
currentThemeKey.value = getCurrentThemeKey();
|
||||
applyThemeToNativeUI(currentThemeKey.value);
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
uni.$off('theme-change', onThemeChanged);
|
||||
});
|
||||
|
||||
@@ -10,6 +10,18 @@ export const THEME_KEYS = {
|
||||
|
||||
export type ThemeKey = (typeof THEME_KEYS)[keyof typeof THEME_KEYS];
|
||||
|
||||
export interface NavBarThemeTokens {
|
||||
backgroundColor: string;
|
||||
frontColor: '#ffffff' | '#000000';
|
||||
}
|
||||
|
||||
export interface TabBarThemeTokens {
|
||||
color: string;
|
||||
selectedColor: string;
|
||||
backgroundColor: string;
|
||||
borderStyle: 'white' | 'black';
|
||||
}
|
||||
|
||||
export interface ThemeTokens {
|
||||
bgPrimary: string;
|
||||
bgSurface: string;
|
||||
@@ -26,6 +38,8 @@ export interface ThemeTokens {
|
||||
textSecondary: string;
|
||||
textMuted: string;
|
||||
shadowBrand: string;
|
||||
navBar: NavBarThemeTokens;
|
||||
tabBar: TabBarThemeTokens;
|
||||
}
|
||||
|
||||
export interface ThemeItem {
|
||||
@@ -55,7 +69,17 @@ export const THEMES: Record<ThemeKey, ThemeItem> = {
|
||||
textPrimary: '#F8FAFC',
|
||||
textSecondary: '#94A3B8',
|
||||
textMuted: '#64748B',
|
||||
shadowBrand: '0 8rpx 24rpx rgba(99, 102, 241, 0.35)'
|
||||
shadowBrand: '0 8rpx 24rpx rgba(99, 102, 241, 0.35)',
|
||||
navBar: {
|
||||
backgroundColor: '#0A0F1D',
|
||||
frontColor: '#ffffff'
|
||||
},
|
||||
tabBar: {
|
||||
color: '#94A3B8',
|
||||
selectedColor: '#6366F1',
|
||||
backgroundColor: '#151D30',
|
||||
borderStyle: 'black'
|
||||
}
|
||||
}
|
||||
},
|
||||
[THEME_KEYS.WARM]: {
|
||||
@@ -77,7 +101,17 @@ export const THEMES: Record<ThemeKey, ThemeItem> = {
|
||||
textPrimary: '#1C1917',
|
||||
textSecondary: '#57534E',
|
||||
textMuted: '#78716C',
|
||||
shadowBrand: '0 8rpx 24rpx rgba(234, 88, 12, 0.25)'
|
||||
shadowBrand: '0 8rpx 24rpx rgba(234, 88, 12, 0.25)',
|
||||
navBar: {
|
||||
backgroundColor: '#FDFBF7',
|
||||
frontColor: '#000000'
|
||||
},
|
||||
tabBar: {
|
||||
color: '#78716C',
|
||||
selectedColor: '#EA580C',
|
||||
backgroundColor: '#FFFFFF',
|
||||
borderStyle: 'white'
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -158,4 +158,78 @@ describe('ThemeManager (TDD 测试套件: 暖色系与双主题设计系统)', (
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe('5. 顶部导航栏 (NavBar) 与底部菜单 (TabBar) 双主题规范校验', () => {
|
||||
it('冷色系 NavBar 必须为深色黑底白字,TabBar 必须为深蓝卡片底', () => {
|
||||
const coolTheme = THEMES[THEME_KEYS.COOL];
|
||||
expect(coolTheme.tokens.navBar).toBeDefined();
|
||||
expect(coolTheme.tokens.navBar.backgroundColor).toBe('#0A0F1D');
|
||||
expect(coolTheme.tokens.navBar.frontColor).toBe('#ffffff');
|
||||
|
||||
expect(coolTheme.tokens.tabBar).toBeDefined();
|
||||
expect(coolTheme.tokens.tabBar.backgroundColor).toBe('#151D30');
|
||||
expect(coolTheme.tokens.tabBar.selectedColor).toBe('#6366F1');
|
||||
});
|
||||
|
||||
it('浅色暖阳晨曦模式下,顶部 NavBar 与底部 TabBar 必须全部为浅色亮底', () => {
|
||||
const warmTheme = THEMES[THEME_KEYS.WARM];
|
||||
expect(warmTheme.tokens.navBar).toBeDefined();
|
||||
expect(warmTheme.tokens.tabBar).toBeDefined();
|
||||
|
||||
// 顶部 NavBar 浅色底 (亮度 >= 0.85),文字为深黑 (#000000)
|
||||
expect(getLuminance(warmTheme.tokens.navBar.backgroundColor)).toBeGreaterThanOrEqual(0.85);
|
||||
expect(warmTheme.tokens.navBar.frontColor).toBe('#000000');
|
||||
|
||||
// 底部 TabBar 浅色底 (纯白或米白,亮度 >= 0.95),选中项高亮为曜橙
|
||||
expect(getLuminance(warmTheme.tokens.tabBar.backgroundColor)).toBeGreaterThanOrEqual(0.95);
|
||||
expect(warmTheme.tokens.tabBar.selectedColor).toBe('#EA580C');
|
||||
expect(warmTheme.tokens.tabBar.borderStyle).toBe('white');
|
||||
});
|
||||
});
|
||||
|
||||
describe('6. 核心 Tab 页面多端生命周期与主题自适应门禁校验', () => {
|
||||
const rootDir = path.resolve(__dirname, '../../');
|
||||
const tabPages = [
|
||||
path.join(rootDir, 'pwuniapp', 'pages', 'index', 'index.vue'),
|
||||
path.join(rootDir, 'pwuniapp', 'pages', 'activity', 'list.vue'),
|
||||
path.join(rootDir, 'pwuniapp', 'pages', 'order', 'list.vue'),
|
||||
path.join(rootDir, 'pwuniapp', 'pages', 'user', 'index.vue'),
|
||||
];
|
||||
|
||||
it('四大 Tab 页面必须全部引入并在 onShow 中调用 applyThemeToNativeUI', () => {
|
||||
for (const pagePath of tabPages) {
|
||||
expect(fs.existsSync(pagePath)).toBe(true);
|
||||
const content = fs.readFileSync(pagePath, 'utf-8');
|
||||
const relativeName = path.relative(rootDir, pagePath);
|
||||
|
||||
expect({
|
||||
file: relativeName,
|
||||
hasApplyTheme: content.includes('applyThemeToNativeUI'),
|
||||
hasOnShow: content.includes('onShow')
|
||||
}).toEqual({
|
||||
file: relativeName,
|
||||
hasApplyTheme: true,
|
||||
hasOnShow: true
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
it('四大 Tab 页面必须包含 theme-warm 根容器类绑定与浅色样式适配', () => {
|
||||
for (const pagePath of tabPages) {
|
||||
const content = fs.readFileSync(pagePath, 'utf-8');
|
||||
const relativeName = path.relative(rootDir, pagePath);
|
||||
|
||||
expect({
|
||||
file: relativeName,
|
||||
hasThemeWarmBind: content.includes('theme-warm'),
|
||||
hasThemeWarmStyle: content.includes('.theme-warm')
|
||||
}).toEqual({
|
||||
file: relativeName,
|
||||
hasThemeWarmBind: true,
|
||||
hasThemeWarmStyle: true
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
在新工单中引用
屏蔽一个用户