用户反馈:① 图标太小 ② 底部导航栏不允许有文字。 - NavItem(底部导航):去掉 Text(item.label) 纯图标,AmIcon 22→28vp - WideSidebar(宽屏侧栏):去掉 label 文字(WebUI Sidebar 本就是 60px 纯图标轨), 导航图标 22→26vp、品牌标 26→30vp;NavItemBuilder 去掉 label 参数 - Theme:新增 glassRadius=14 / paneGap=10(与 WebUI app-shell CSS 变量同值, 用于宽屏玻璃面板几何;原有 radiusCard 保持系统跟随不动) - 判据同步:harmony-nav ⑤ 改纯图标(1 处三元式 + 无文字 + 28vp)+ 变异自检三项; harmony-widescreen ③ 同样改纯图标(1 处 + 无文字 + 26vp)
90 lines
5.0 KiB
JavaScript
90 lines
5.0 KiB
JavaScript
// 宽屏侧栏图标轨(WideSidebar)判据 —— 一比一复刻 WebUI 的 `Sidebar`(60px 图标轨)。
|
||
//
|
||
// WebUI 的 `Sidebar`(components/Sidebar.tsx)是 60px 宽的图标列:
|
||
// 品牌标(顶) / 通信·日历·联系人(中) / 设置(底)
|
||
// 选中态 = 图标+文字变色 + 品牌浅底,**不加背景块/指示条**。
|
||
//
|
||
// 鸿蒙侧原来是**没有**宽屏布局的(只有底部导航条),WideSidebar 补的就是
|
||
// "宽屏模式"这半:≥768vp 时 MainPage 挂侧栏、藏底部条(见 MainPage.build 的 onAreaChange)。
|
||
// 这条判据钉的是 Sidebar 自己的形状:宽 60vp、三项导航 + 设置、选中态只换颜色。
|
||
|
||
import { code, prose, stripComments } from './lib/read.mjs';
|
||
import { dirname, join } from 'node:path';
|
||
import { fileURLToPath } from 'node:url';
|
||
import { test } from 'node:test';
|
||
import assert from 'node:assert/strict';
|
||
|
||
const HERE = dirname(fileURLToPath(import.meta.url));
|
||
const ROOT = join(HERE, '..', '..', '..');
|
||
const HARMONY_ETS = join(ROOT, 'client/harmony/entry/src/main/ets');
|
||
|
||
const read = p => prose(join(HARMONY_ETS, p));
|
||
|
||
/** 取某个成员/方法正文(按行切到下一个成员声明) */
|
||
function memberBody(src, signature) {
|
||
const lines = src.split('\n');
|
||
const start = lines.findIndex(l => l.includes(signature));
|
||
assert.ok(start > 0, `要能找到 ${signature}`);
|
||
let stop = lines.length;
|
||
for (let i = start + 1; i < lines.length; i++) {
|
||
if (/^ (@Builder|build\(|NavItemBuilder\()/.test(lines[i])) { stop = i; break; }
|
||
}
|
||
return lines.slice(start, stop).join('\n');
|
||
}
|
||
|
||
test('① 宽度:SIDEBAR_WIDTH = 60vp(WebUI 的 `w-[60px]` 是同一数字)', () => {
|
||
const sidebar = read('pages/WideSidebar.ets');
|
||
const code_ = stripComments(sidebar);
|
||
assert.match(code_, /export const SIDEBAR_WIDTH: number = 60\s*;/, '要导出 60 这个常量');
|
||
const main = read('pages/MainPage.ets');
|
||
assert.match(main, /WideSidebar\(/, 'MainPage 要真正挂 WideSidebar');
|
||
});
|
||
|
||
test('② 三项导航 + 设置按钮:内容与 WebUI Sidebar 对齐', () => {
|
||
const sidebar = read('pages/WideSidebar.ets');
|
||
// NAV_ITEMS 遍历(与底部导航同一份清单 —— 加项两边同时出现)
|
||
assert.match(sidebar, /ForEach\(NAV_ITEMS,/, '要遍历 NAV_ITEMS(与底部导航同一清单)');
|
||
// 品牌标 + 三项导航 + 设置(与 WebUI:brand / nav / settings 的分组一致)
|
||
assert.match(sidebar, /品牌标/, '要有品牌标(注释里的分组依据)');
|
||
assert.match(sidebar, /iconName: 'person'/, '设置按钮要用 person 图标(WebUI 侧沿用的同一枚)');
|
||
assert.match(sidebar, /onSettings/, '设置按钮要回调 onSettings(点击后由 MainPage 路由)');
|
||
});
|
||
|
||
test('③ 选中态只换颜色(与底部导航同一套纪律):纯图标、无文字', () => {
|
||
const sidebar = read('pages/WideSidebar.ets');
|
||
const code_ = stripComments(sidebar);
|
||
/*
|
||
* 2026-09-16 用户:「底部导航栏不允许有文字」⇒ 侧栏同样走纯图标。
|
||
* WebUI 的 `Sidebar.tsx` 本就是 60px 纯图标轨(无 label 文字)。
|
||
*/
|
||
const active = /this\.currentIndex === index \? Theme\.navFgActive : Theme\.navFg/g;
|
||
const hits = code_.match(active) || [];
|
||
assert.equal(hits.length, 1,
|
||
`侧栏导航项只应有 1 处选中三元式(现在 ${hits.length} 处)— 纯图标,无文字`);
|
||
// 无文字(label 的 Text)
|
||
assert.ok(!/Text\(label\)/.test(code_),
|
||
'侧栏是纯图标轨:不允许有 label 文字(WebUI Sidebar 无文字)');
|
||
// 图标不能太小(26vp)
|
||
assert.match(code_, /iconSize: 26/,
|
||
'侧栏导航图标要 26vp(WebUI 是 24,鸿蒙放大一档 —— 用户嫌 22 太小)');
|
||
// 不加背景块 / 指示条
|
||
assert.ok(!/currentIndex[^{;]{0,40}backgroundColor/.test(code_),
|
||
'选中态不许改背景色(与底部导航同一纪律:变色即可)');
|
||
});
|
||
|
||
test('④ MainPage 接线:宽屏才挂侧栏、宽屏藏底部条、断点 768', () => {
|
||
const main = read('pages/MainPage.ets');
|
||
const code_ = stripComments(main);
|
||
// 宽屏分支:isWide 时才渲染 WideSidebar
|
||
assert.match(main, /if \(this\.isWide\) \{/, '侧栏要包在 isWide 分支里');
|
||
assert.match(code_, /WideSidebar\(\{/, '侧栏要真挂在 build 里(剥注释后仍存在)');
|
||
// 窄屏 x 宽屏:底部条只要窄屏有 —— 两半都是条件式的,不是同时出现
|
||
assert.match(main, /if \(!this\.isWide\) \{/, '底部导航条要包在 !isWide 分支里');
|
||
const both = /if \(this\.isWide\) \{[\s\S]*?if \(!this\.isWide\)/.test(main);
|
||
assert.ok(both, 'isWide 与 !isWide 两分支要在同一个结构里(互斥)');
|
||
// 断点检测
|
||
assert.match(code_, /onAreaChange/, '要用 onAreaChange 实时检测窗口宽度');
|
||
assert.match(code_, />=\s*768/s, '断点是 768(与 WebUI 的 lg 断点同一档)');
|
||
// let为0(宽屏没有底部条,内容 padding 归零)
|
||
assert.match(code_, /bottom:\s*this\.isWide \? 0 : NAV_CONTENT_RESERVE/, '宽屏内容 padding 要归零(没有底部条了)');
|
||
}); |