feat(theme): 完善顶部导航栏与底部菜单浅色暖色系适配及多端Tab生命周期同步
这个提交包含在:
@@ -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
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
在新工单中引用
屏蔽一个用户