From 63e81995ad591383b07f3f7ac5c4e106741aad5b Mon Sep 17 00:00:00 2001 From: wikiboss Date: Wed, 16 Sep 2026 20:22:18 +0800 Subject: [PATCH] =?UTF-8?q?fix(ui):=20=E4=BF=AE=E5=A4=8D=E9=A6=96=E9=A1=B5?= =?UTF-8?q?=E8=AF=95=E5=90=AC=E6=9D=A1=E6=96=87=E5=AD=97=E6=8A=98=E8=A1=8C?= =?UTF-8?q?=E9=97=AE=E9=A2=98=EF=BC=8C=E5=AE=8C=E5=96=84=E5=8D=95=E8=A1=8C?= =?UTF-8?q?=E6=96=87=E6=9C=AC=E7=9C=81=E7=95=A5=E6=88=AA=E6=96=AD=E8=A7=84?= =?UTF-8?q?=E8=8C=83=E4=B8=8E=E6=96=87=E6=A1=88=E7=B2=BE=E7=AE=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pwuniapp/App.vue | 32 ++++++------- pwuniapp/common/mock.js | 4 +- pwuniapp/common/theme.js | 30 ++++++------ pwuniapp/pages/index/index.vue | 65 +++++++++++++++----------- pwuniapp/pages/user/index.vue | 6 +-- pwuniapp/uni.scss | 30 ++++++------ server/src/core/theme/theme.manager.ts | 30 ++++++------ server/tests/no-emoji.spec.ts | 33 +++++++++++-- server/tests/theme.spec.ts | 21 ++++++--- 9 files changed, 146 insertions(+), 105 deletions(-) diff --git a/pwuniapp/App.vue b/pwuniapp/App.vue index ec7a20f..6b119b4 100644 --- a/pwuniapp/App.vue +++ b/pwuniapp/App.vue @@ -35,26 +35,26 @@ export default { --shadow-brand: 0 8rpx 24rpx rgba(99, 102, 241, 0.35); } -/* 暖阳赤焰暖色系主题 (Sunset Amber & Warm Ember) */ +/* 浅色暖阳晨曦主题 (Light Warm Sunset Morning) */ page.theme-warm, .theme-warm { - --bg-primary: #140E0A; - --bg-surface: #221711; - --bg-surface-elevated: #2E1F17; - --bg-surface-glass: rgba(34, 23, 17, 0.85); - --color-brand: #F97316; - --color-brand-light: #FB923C; + --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(249, 115, 22, 0.35); - --color-brand-gradient: linear-gradient(135deg, #F97316, #F59E0B); - --border-subtle: #342217; + --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: #FFF7ED; - --text-secondary: #C7B5A7; - --text-muted: #8C7565; - --shadow-brand: 0 8rpx 24rpx rgba(249, 115, 22, 0.35); + --text-primary: #1C1917; + --text-secondary: #57534E; + --text-muted: #78716C; + --shadow-brand: 0 8rpx 24rpx rgba(234, 88, 12, 0.25); - background-color: #140E0A; - color: #FFF7ED; + background-color: #FDFBF7; + color: #1C1917; } /* 全局暗黑电竞基础重置 (严格符合 UI/UX Pro Max 规范) */ diff --git a/pwuniapp/common/mock.js b/pwuniapp/common/mock.js index 0c8cc8e..829a394 100644 --- a/pwuniapp/common/mock.js +++ b/pwuniapp/common/mock.js @@ -64,7 +64,7 @@ export const EXPERTS_LIST = [ isOnline: true, voiceDuration: 18, voiceType: 'song', - voiceTitle: '歌声试听 · 《晴天》甜美对唱', + voiceTitle: '歌声 · 《晴天》', bio: '音乐学院流行演唱在读,精通流行热门情歌与粤语金曲,KTV对唱超好听,包厢气氛组担当~限正规公开量贩KTV。', photos: ['https://images.unsplash.com/photo-1516450360452-9312f5e86fc7?w=500&fit=crop'], services: [ @@ -119,7 +119,7 @@ export const EXPERTS_LIST = [ isOnline: true, voiceDuration: 20, voiceType: 'song', - voiceTitle: '歌声试听 · 摇滚流行高音', + voiceTitle: '歌声 · 摇滚高音', bio: '高校乐队主唱,吉他弹唱/流行摇滚,KTV气氛直接拉满,绝不冷场,带你体验演唱会包厢~', photos: ['https://images.unsplash.com/photo-1511671782779-c97d3d27a1d4?w=500&fit=crop'], services: [ diff --git a/pwuniapp/common/theme.js b/pwuniapp/common/theme.js index c65a4e6..cb60448 100644 --- a/pwuniapp/common/theme.js +++ b/pwuniapp/common/theme.js @@ -33,24 +33,24 @@ export const THEMES = { }, [THEME_KEYS.WARM]: { key: THEME_KEYS.WARM, - name: '暖阳赤焰', - description: '深邃暖焦糖褐与暖阳曜橙流光,热情温馨有活力', + name: '暖阳晨曦', + description: '明亮温润的奶油米白与暖阳曜橙流光,温馨治愈轻快', tokens: { - bgPrimary: '#140E0A', - bgSurface: '#221711', - bgSurfaceElevated: '#2E1F17', - bgSurfaceGlass: 'rgba(34, 23, 17, 0.85)', - colorBrand: '#F97316', - colorBrandLight: '#FB923C', + bgPrimary: '#FDFBF7', + bgSurface: '#FFFFFF', + bgSurfaceElevated: '#F8F5F0', + bgSurfaceGlass: 'rgba(255, 255, 255, 0.90)', + colorBrand: '#EA580C', + colorBrandLight: '#F97316', colorBrandGold: '#F59E0B', - colorBrandGlow: 'rgba(249, 115, 22, 0.35)', - colorBrandGradient: 'linear-gradient(135deg, #F97316, #F59E0B)', - borderSubtle: '#342217', + colorBrandGlow: 'rgba(234, 88, 12, 0.18)', + colorBrandGradient: 'linear-gradient(135deg, #F97316, #FB923C)', + borderSubtle: '#F0ECE4', borderFocus: '#EA580C', - textPrimary: '#FFF7ED', - textSecondary: '#C7B5A7', - textMuted: '#8C7565', - shadowBrand: '0 8rpx 24rpx rgba(249, 115, 22, 0.35)' + textPrimary: '#1C1917', + textSecondary: '#57534E', + textMuted: '#78716C', + shadowBrand: '0 8rpx 24rpx rgba(234, 88, 12, 0.25)' } } }; diff --git a/pwuniapp/pages/index/index.vue b/pwuniapp/pages/index/index.vue index feed750..47bbfee 100644 --- a/pwuniapp/pages/index/index.vue +++ b/pwuniapp/pages/index/index.vue @@ -625,11 +625,47 @@ const navTo = (url) => { padding: 0 16rpx; margin-bottom: 16rpx; transition: all 0.2s ease; + box-sizing: border-box; white-space: nowrap; - text-overflow: ellipsis; overflow: hidden; flex-shrink: 0; + .voice-icon-svg { + width: 20rpx; + height: 20rpx; + margin-right: 8rpx; + flex-shrink: 0; + } + + .voice-text { + flex: 1; + min-width: 0; + font-size: 20rpx; + color: #818CF8; + font-weight: 600; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } + + .wave-lines { + display: flex; + align-items: flex-end; + gap: 4rpx; + margin-left: 8rpx; + flex-shrink: 0; + + .wave-item { + width: 4rpx; + background: #818CF8; + border-radius: 2rpx; + + &.w1 { height: 14rpx; animation: bounce 0.6s infinite ease-in-out; } + &.w2 { height: 22rpx; animation: bounce 0.6s infinite ease-in-out 0.2s; } + &.w3 { height: 10rpx; animation: bounce 0.6s infinite ease-in-out 0.4s; } + } + } + &.playing { background: rgba(99, 102, 241, 0.3); border-color: #818CF8; @@ -654,33 +690,6 @@ const navTo = (url) => { background: #FB7185; } } - - .voice-icon-svg { - width: 20rpx; - height: 20rpx; - margin-right: 8rpx; - } - .voice-text { - font-size: 20rpx; - color: #818CF8; - font-weight: 600; - } - .wave-lines { - display: flex; - align-items: flex-end; - gap: 4rpx; - margin-left: 8rpx; - - .wave-item { - width: 4rpx; - background: #818CF8; - border-radius: 2rpx; - - &.w1 { height: 14rpx; animation: bounce 0.6s infinite ease-in-out; } - &.w2 { height: 22rpx; animation: bounce 0.6s infinite ease-in-out 0.2s; } - &.w3 { height: 10rpx; animation: bounce 0.6s infinite ease-in-out 0.4s; } - } - } } .card-footer { diff --git a/pwuniapp/pages/user/index.vue b/pwuniapp/pages/user/index.vue index cd96329..5d206a8 100644 --- a/pwuniapp/pages/user/index.vue +++ b/pwuniapp/pages/user/index.vue @@ -96,7 +96,7 @@ 界面主题风格 - {{ currentThemeKey === 'warm' ? '暖阳赤焰' : '冷光暗夜' }} + {{ currentThemeKey === 'warm' ? '浅色暖阳' : '冷光暗夜' }} > @@ -144,13 +144,13 @@ onUnmounted(() => { const handleSwitchTheme = () => { uni.showActionSheet({ - itemList: ['冷光暗夜 (经典暗夜蓝紫)', '暖阳赤焰 (热情暖橙金流光)'], + itemList: ['冷光暗夜 (经典电竞暗黑)', '浅色暖阳 (温馨奶油米白·暖橙)'], success: (res) => { const selectedKey = res.tapIndex === 1 ? THEME_KEYS.WARM : THEME_KEYS.COOL; currentThemeKey.value = selectedKey; setTheme(selectedKey); uni.showToast({ - title: selectedKey === THEME_KEYS.WARM ? '已切换至【暖阳赤焰】暖色系' : '已切换至【冷光暗夜】经典款', + title: selectedKey === THEME_KEYS.WARM ? '已切换至【浅色暖阳】主题' : '已切换至【冷光暗夜】经典款', icon: 'none', duration: 1500 }); diff --git a/pwuniapp/uni.scss b/pwuniapp/uni.scss index cd84984..eb2cce8 100644 --- a/pwuniapp/uni.scss +++ b/pwuniapp/uni.scss @@ -43,22 +43,22 @@ $uni-color-primary: #6366F1; $uni-bg-color: #0A0F1D; $uni-text-color: #F8FAFC; -/* 7. 暖阳赤焰暖色系专属 Tokens (Sunset Amber & Warm Ember) */ -$warm-bg-primary: #140E0A; // 暖夜焦糖深褐黑 -$warm-bg-surface: #221711; // 暖色卡片底色 -$warm-bg-surface-elevated: #2E1F17; // 暖色浮层底色 -$warm-bg-surface-glass: rgba(34, 23, 17, 0.85); // 暖色拟态磨砂玻璃 +/* 7. 浅色暖阳晨曦专属 Tokens (Light Warm Sunset Morning) */ +$warm-bg-primary: #FDFBF7; // 页面最底色 (温润奶油米白) +$warm-bg-surface: #FFFFFF; // 卡片底色 (高洁暖白) +$warm-bg-surface-elevated: #F8F5F0; // 浮层底色 (浅暖米杏) +$warm-bg-surface-glass: rgba(255, 255, 255, 0.90); // 暖白透亮磨砂玻璃 -$warm-color-brand: #F97316; // 暖阳曜橙 (主品牌色) -$warm-color-brand-light: #FB923C; // 暖橙高光 +$warm-color-brand: #EA580C; // 核心曜橙 (高对比度聚焦色) +$warm-color-brand-light: #F97316; // 暖橙高光 $warm-color-brand-gold: #F59E0B; // 暖金流光 -$warm-color-brand-glow: rgba(249, 115, 22, 0.35); // 暖橙发光光晕 -$warm-color-brand-gradient: linear-gradient(135deg, #F97316, #F59E0B); +$warm-color-brand-glow: rgba(234, 88, 12, 0.18); // 柔和发光光晕 +$warm-color-brand-gradient: linear-gradient(135deg, #F97316, #FB923C); -$warm-text-primary: #FFF7ED; // 暖白高光文本 -$warm-text-secondary: #C7B5A7; // 暖灰次级文本 -$warm-text-muted: #8C7565; // 暖咖三级文本 -$warm-border-subtle: #342217; // 暖色边框 -$warm-border-focus: #EA580C; // 暖色聚焦边框 -$warm-shadow-brand: 0 8rpx 24rpx rgba(249, 115, 22, 0.35); +$warm-text-primary: #1C1917; // 暖炭黑一级主文本 (对比度 > 15:1) +$warm-text-secondary: #57534E; // 暖深灰二级描述文本 (对比度 > 7:1) +$warm-text-muted: #78716C; // 暖中灰三级占位说明 +$warm-border-subtle: #F0ECE4; // 浅米暖灰边框 +$warm-border-focus: #EA580C; // 聚焦边框 +$warm-shadow-brand: 0 8rpx 24rpx rgba(234, 88, 12, 0.25); diff --git a/server/src/core/theme/theme.manager.ts b/server/src/core/theme/theme.manager.ts index 222db8b..f74c0c0 100644 --- a/server/src/core/theme/theme.manager.ts +++ b/server/src/core/theme/theme.manager.ts @@ -60,24 +60,24 @@ export const THEMES: Record = { }, [THEME_KEYS.WARM]: { key: THEME_KEYS.WARM, - name: '暖阳赤焰', - description: '深邃暖焦糖褐与暖阳曜橙流光,热情温馨有活力', + name: '暖阳晨曦', + description: '明亮温润的奶油米白与暖阳曜橙流光,温馨治愈轻快', tokens: { - bgPrimary: '#140E0A', - bgSurface: '#221711', - bgSurfaceElevated: '#2E1F17', - bgSurfaceGlass: 'rgba(34, 23, 17, 0.85)', - colorBrand: '#F97316', - colorBrandLight: '#FB923C', + bgPrimary: '#FDFBF7', + bgSurface: '#FFFFFF', + bgSurfaceElevated: '#F8F5F0', + bgSurfaceGlass: 'rgba(255, 255, 255, 0.90)', + colorBrand: '#EA580C', + colorBrandLight: '#F97316', colorBrandGold: '#F59E0B', - colorBrandGlow: 'rgba(249, 115, 22, 0.35)', - colorBrandGradient: 'linear-gradient(135deg, #F97316, #F59E0B)', - borderSubtle: '#342217', + colorBrandGlow: 'rgba(234, 88, 12, 0.18)', + colorBrandGradient: 'linear-gradient(135deg, #F97316, #FB923C)', + borderSubtle: '#F0ECE4', borderFocus: '#EA580C', - textPrimary: '#FFF7ED', - textSecondary: '#C7B5A7', - textMuted: '#8C7565', - shadowBrand: '0 8rpx 24rpx rgba(249, 115, 22, 0.35)' + textPrimary: '#1C1917', + textSecondary: '#57534E', + textMuted: '#78716C', + shadowBrand: '0 8rpx 24rpx rgba(234, 88, 12, 0.25)' } } }; diff --git a/server/tests/no-emoji.spec.ts b/server/tests/no-emoji.spec.ts index d9a708a..7657d1a 100644 --- a/server/tests/no-emoji.spec.ts +++ b/server/tests/no-emoji.spec.ts @@ -73,20 +73,43 @@ describe('UI/UX 规范门禁 (TDD 测试套件: 全面杜绝系统 Emoji)', () = }); describe('4. 首页卡片试听条单行防折行与文本截断规范校验', () => { - it('首页试听条必须配置单行不折行、弹性伸缩与省略号截断', () => { + it('首页试听条容器及文字必须配置单行不折行、弹性伸缩与省略号截断', () => { const indexVuePath = path.join(uniPagesDir, 'index', 'index.vue'); const content = fs.readFileSync(indexVuePath, 'utf-8'); - // 提取 .voice-bar 样式块 + // 1. 验证 .voice-bar 容器样式 const voiceBarMatch = content.match(/\.voice-bar\s*\{([\s\S]*?)\n\s*\.card-footer/); expect(voiceBarMatch).not.toBeNull(); const styleBlock = voiceBarMatch![1]; - // 必须防止文字折行破坏胶囊造型 + expect(styleBlock).toContain('box-sizing: border-box'); expect(styleBlock).toContain('white-space: nowrap'); - expect(styleBlock).toContain('text-overflow: ellipsis'); expect(styleBlock).toContain('overflow: hidden'); - expect(styleBlock).toContain('flex-shrink: 0'); + + // 2. 验证 .voice-icon-svg 必须防止被弹性挤压 + const iconMatch = styleBlock.match(/\.voice-icon-svg\s*\{([\s\S]*?)\}/); + expect(iconMatch).not.toBeNull(); + expect(iconMatch![1]).toContain('flex-shrink: 0'); + + // 3. 验证 .voice-text 核心文本必须具有单行截断三件套与 flex 约束 + const textMatch = styleBlock.match(/\.voice-text\s*\{([\s\S]*?)\}/); + expect(textMatch).not.toBeNull(); + const textStyle = textMatch![1]; + expect(textStyle).toContain('flex: 1'); + expect(textStyle).toContain('min-width: 0'); + expect(textStyle).toContain('white-space: nowrap'); + expect(textStyle).toContain('overflow: hidden'); + expect(textStyle).toContain('text-overflow: ellipsis'); + }); + + it('mock.js 中试听标题长度必须精简且不得超过12个字,防止在小屏过早被截断', () => { + const mockJsPath = path.join(rootDir, 'pwuniapp', 'common', 'mock.js'); + const mockContent = fs.readFileSync(mockJsPath, 'utf-8'); + const voiceTitleMatches = mockContent.matchAll(/voiceTitle:\s*['"]([^'"]+)['"]/g); + for (const match of voiceTitleMatches) { + const title = match[1]; + expect(title.length).toBeLessThanOrEqual(12); + } }); }); }); diff --git a/server/tests/theme.spec.ts b/server/tests/theme.spec.ts index fe8edad..7b655cd 100644 --- a/server/tests/theme.spec.ts +++ b/server/tests/theme.spec.ts @@ -82,8 +82,17 @@ describe('ThemeManager (TDD 测试套件: 暖色系与双主题设计系统)', ( }); }); - describe('2. WCAG AA 级无障碍色彩对比度验证', () => { - it('暖色系一级主文本 (textPrimary) 对底色与卡片底色对比度必须 >= 7:1 (超越 AA 级 4.5:1)', () => { + describe('2. WCAG AA 级无障碍色彩对比度与浅色特征验证', () => { + it('浅色暖色系底色必须为明亮浅色 (相对亮度 > 0.85)', () => { + const tokens = THEMES[THEME_KEYS.WARM].tokens; + const bgLum = getLuminance(tokens.bgPrimary); + const surfaceLum = getLuminance(tokens.bgSurface); + + expect(bgLum).toBeGreaterThanOrEqual(0.85); + expect(surfaceLum).toBeGreaterThanOrEqual(0.95); + }); + + it('浅色暖色系一级主文本 (textPrimary) 对浅色底与卡片底色对比度必须 >= 7:1 (超越 AA 级 4.5:1)', () => { const tokens = THEMES[THEME_KEYS.WARM].tokens; const ratioOnBg = getContrastRatio(tokens.textPrimary, tokens.bgPrimary); const ratioOnSurface = getContrastRatio(tokens.textPrimary, tokens.bgSurface); @@ -92,7 +101,7 @@ describe('ThemeManager (TDD 测试套件: 暖色系与双主题设计系统)', ( expect(ratioOnSurface).toBeGreaterThanOrEqual(7.0); }); - it('暖色系二级辅助文本 (textSecondary) 对底色对比度必须 >= 4.5:1 (符合 WCAG AA 标准)', () => { + it('浅色暖色系二级辅助文本 (textSecondary) 对浅色底对比度必须 >= 4.5:1 (符合 WCAG AA 标准)', () => { const tokens = THEMES[THEME_KEYS.WARM].tokens; const ratio = getContrastRatio(tokens.textSecondary, tokens.bgPrimary); @@ -106,12 +115,12 @@ describe('ThemeManager (TDD 测试套件: 暖色系与双主题设计系统)', ( expect(themeManager.getCurrentTheme().name).toBe('冷光暗夜'); }); - it('成功切换到 warm (暖阳赤焰) 主题', () => { + it('成功切换到 warm (暖阳晨曦) 浅色暖色系主题', () => { const current = themeManager.switchTheme(THEME_KEYS.WARM); expect(current.key).toBe(THEME_KEYS.WARM); - expect(current.name).toBe('暖阳赤焰'); + expect(current.name).toBe('暖阳晨曦'); expect(themeManager.getCurrentThemeKey()).toBe(THEME_KEYS.WARM); - expect(themeManager.getCurrentTokens().colorBrand).toBe('#F97316'); + expect(themeManager.getCurrentTokens().colorBrand).toBe('#EA580C'); }); it('传入非法主题标识时,应平滑回退到默认 cool 主题,确保系统不崩溃', () => {