From 79e591aa8b6d22ce832d47868a357afca10afc6a Mon Sep 17 00:00:00 2001 From: pi Date: Mon, 14 Sep 2026 18:09:59 +0800 Subject: [PATCH] =?UTF-8?q?=E8=B7=A8=E7=AB=AF:=20=E5=BA=95=E9=83=A8?= =?UTF-8?q?=E5=AF=BC=E8=88=AA=E9=80=89=E4=B8=AD=E6=80=81=E2=80=94=E2=80=94?= =?UTF-8?q?=E5=9B=BE=E6=A0=87=E4=B9=9F=E5=8F=98=E8=89=B2=EF=BC=88=E9=B8=BF?= =?UTF-8?q?=E8=92=99=E4=BE=A7=E8=A1=A5=E9=BD=90=EF=BC=89=EF=BC=8C=E9=80=89?= =?UTF-8?q?=E4=B8=AD=E6=80=81=E5=8F=AA=E6=8D=A2=E9=A2=9C=E8=89=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 用户:「ui更新同步到鸿蒙端」+「选中对应的文字和图标变色即可」。 WebUI(上一提交):删掉背景块与顶部指示条,只留颜色。 鸿蒙侧:本来就没有背景/指示条(选中态从没用形状表达过),缺的是**图标那一半** —— MainPage.NavItem 里只有 label 上了 fontColor,图标一直保持默认色,看着像选中了一半。 - MainPage.NavItem:图标补 fontColor,与 label 过同一个三元式 - 判据 harmony-nav ⑤ + 真变异自检(删掉图标那行 fontColor,⑤ 立刻红) - 自检本身也修了一处窗口式判据:原来用 [\s\S]{0,80} 找 fontColor, 把下一行 label 的也圈了进来,自检自己假绿 - 模拟器实测(harmony-emu + hvigorw + hdc + uitest):同一字形在两项之间颜色随选中**对调** (核心色 81,121,187 选中 vs 135,168,217 未选中) - 提交归属:本提交同时动 harmony 与 electron,按仓库判据自报家门(跨端:) --- client/electron/test/harmony-nav.test.mjs | 54 +++++++++++++++++++ .../entry/src/main/ets/pages/MainPage.ets | 14 ++++- 2 files changed, 67 insertions(+), 1 deletion(-) diff --git a/client/electron/test/harmony-nav.test.mjs b/client/electron/test/harmony-nav.test.mjs index c2adf1d..a279f7d 100644 --- a/client/electron/test/harmony-nav.test.mjs +++ b/client/electron/test/harmony-nav.test.mjs @@ -233,3 +233,57 @@ test('★ 玻璃只在两处、且这一处是"背后有可变内容"(GLASS assert.match(navDoc, /会滚动的内容|滚动内容/, '要写清"为什么这一处可以有材质"(背后是可变内容)'); assert.match(navDoc, /GLASS_REGISTRY/, '要指名登记册,后人查得到放行流程'); }); + +/** + * ⑤ 选中态:**只换颜色**,且**图标与文字都换** —— 与 WebUI 同一套表达。 + * + * 用户(2026-09-14):「同时底部导航栏选中对应的文字和图标变色即可」。 + * 这条要求有两半,缺任何一半都会变成"假同步": + * · **只有颜色**:多一个背景块或指示条就不是"即可"了(WebUI 侧刚删掉这两样, + * `NarrowNav.tsx` 的 `bg-blue-400` 指示条与 `.nav-item` 的 nav-active-bg); + * · **图标也要变**:鸿蒙侧原来只给 label 上了色,图标保持默认色 —— + * 结构上"存在选中态"、看上去却像选中了一半。图标是文本字形(`item.icon`), + * 所以它必须和 label 过**同一个**三元式。 + * + * 跨端对齐:这条与 WebUI 的 `nav-merge.test.mjs ④` 是同一条要求的两端实现, + * 两边各自钉住自己的写法(`cross-client-*` 那几条钉的是共享数值,不是这里)。 + */ +test('⑤ 选中态只换颜色:图标与文字都变色,且不引入背景/指示条', () => { + const item = builderBody(main, 'NavItem(item: NavItem, index: number) {'); + const itemCode = stripComments(item); + const active = /this\.currentIndex === index \? Theme\.navFgActive : Theme\.navFg/g; + const hits = itemCode.match(active) || []; + assert.equal(hits.length, 2, + `图标与文字都要过同一个选中三元式(现在 ${hits.length} 处)—— 只给文字上色就是"选中了一半"`); + // 图标(item.icon)与文字(item.label)各自紧跟着那个三元式 + const icon = itemCode.slice(itemCode.indexOf('Text(item.icon)'), itemCode.indexOf('Text(item.label)')); + assert.match(icon, /fontColor\(this\.currentIndex === index \? Theme\.navFgActive : Theme\.navFg\)/, + '图标的 fontColor 必须跟着选中态走'); + // 反面:选中态不得靠形状表达(背景 / 圆角块 / 下划线元素) + assert.ok(!/backgroundColor\([^)]*currentIndex/.test(itemCode), + '选中态不许改背景色("变色即可",形状是另一套语言)'); + assert.ok(!/Divider\(|\.borderRadius\([^)]*currentIndex/.test(itemCode), + '选中态不许加指示条 / 圆角块'); + // 选中色与未选中色必须真的是两个不同来源(都指向同一个令牌就成了恒等) + const theme = read('common/Theme.ets'); + assert.match(theme, /static readonly navFgActive: string = Theme\.accentStrong/, + '选中色取品牌深色变体'); + assert.match(theme, /static readonly navFg: Resource = \$r\('sys\.color\.ohos_id_color_text_secondary'\)/, + '未选中色取系统次要文字色(不手写色值)'); +}); + +/** ⑤ 的变异自检:把图标那行退回"只给文字上色",判据必须红。 */ +test('★ ⑤ 变异自检:图标不上色(改造前的写法)必须被判红', () => { + const oldIconLine = 'Text(item.icon).fontSize(20)'; + const itemCode = `Column() {\n ${oldIconLine}\n Text(item.label)\n .fontColor(this.currentIndex === index ? Theme.navFgActive : Theme.navFg)\n }`; + const hits = itemCode.match(/this\.currentIndex === index \? Theme\.navFgActive : Theme\.navFg/g) || []; + assert.equal(hits.length, 1, '旧写法只有 label 上色 ⇒ ⑤ 的"必须两处"会命中它'); + /* + * 判定窗口必须与 ⑤ **完全同一条规则**:从 `Text(item.icon)` 切到下一个 `Text(`。 + * 我第一版在这里写的是 `Text\(item\.icon\)[\s\S]{0,80}fontColor` —— 那个窗口 + * 把**下一行 label 的** fontColor 也圈进来了,于是"旧写法没有图标上色"这条 + * 自检自己绿了(正是本仓库反复记的"窗口式判据")。判据被它咬了一次。 + */ + const icon = itemCode.slice(itemCode.indexOf('Text(item.icon)'), itemCode.indexOf('Text(', itemCode.indexOf('Text(item.icon)') + 1)); + assert.ok(!/fontColor/.test(icon), `旧写法里图标没有 fontColor ⇒ ⑤ 的图标那一半会命中它(切片=${JSON.stringify(icon)})`); +}); diff --git a/client/harmony/entry/src/main/ets/pages/MainPage.ets b/client/harmony/entry/src/main/ets/pages/MainPage.ets index dd5e391..ad18722 100644 --- a/client/harmony/entry/src/main/ets/pages/MainPage.ets +++ b/client/harmony/entry/src/main/ets/pages/MainPage.ets @@ -1687,7 +1687,19 @@ struct MainPage { @Builder NavItem(item: NavItem, index: number) { Column() { - Text(item.icon).fontSize(20) + /* + * 选中态**只换颜色**,而且**图标与文字都要换**。 + * + * 用户(2026-09-14):「同时底部导航栏选中对应的文字和图标变色即可」。 + * 这与 WebUI 侧是同一件事:那边删掉了背景块与顶部指示条、只留颜色 + * (`NarrowNav.tsx` / `.narrow-nav .nav-item[data-active='true']`)。 + * 鸿蒙这一侧本来就没有背景 / 指示条(选中态从没用形状表达过), + * 缺的是**图标这一半**:原来只有 label 上了色,图标一直是默认色, + * 看上去像「选中了一半」。两处都过同一个三元式,避免以后只改一处。 + */ + Text(item.icon) + .fontSize(20) + .fontColor(this.currentIndex === index ? Theme.navFgActive : Theme.navFg) Text(item.label) .fontSize(Theme.fontTiny) .fontColor(this.currentIndex === index ? Theme.navFgActive : Theme.navFg)