Files
MailUI4Agents/client/electron/test/manual/rotate-verify.mjs
JianFeeeee 8a9bc58433 feat(webui): 横竖屏自适应(紧凑双栏)+ 旋屏重算高度
用户:「为什么窄屏的横屏和竖屏没有自适应」。

## 根因

断点是**纯宽度**的:`(max-width: 1023px)`。手机竖屏 390 与横屏 844 **都落在同一档**
⇒ 布局一个像素都不变,横屏多出来的 ~450px 全浪费在空白上。看起来就是"没自适应"。

## 改动

- 新增 `useCompactTwoPane()`:`(min-width: 700px) and (max-height: 560px)`
  —— 仍是紧凑外壳(悬浮底部导航),但内容区从**覆盖式**改成**列表 + 详情并排**。
  用高度而不是 `landscape` 判:桌面窗口压扁、分屏、软键盘弹起都会命中,
  而它们要的是同一件事(别浪费横向空间)。
- App:`compactTwoPane && hasList` 时走并排分支,其余情况仍是 NarrowStack 覆盖式。
- `--app-height` 增加 `orientationchange` 监听并延后一帧重算(iOS 上部分版本的
  resize 不跟着方向变化走;立刻读会拿到旧高度)。

## 判据

`test/manual/rotate-verify.mjs` 8 条,含**可逆性**与前置对照:
竖屏覆盖式 → 横屏并排(真的换了 class)→ 旋回竖屏恢复覆盖式;
三态的 `--app-height` 分别为 844 / 390 / 844(不是旧值);横屏无横向溢出、
底部导航仍完整可见且浮着(left=20)。实测 **8/8**。

同一轮还补上了 `test/manual/calendar-swipe-verify.mjs`(日历滑动,4 条)。
2026-09-14 11:13:24 +08:00

64 lines
3.0 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* 横竖屏自适应验收2026-09-14 用户:「为什么窄屏的横屏和竖屏没有自适应」)。
*
* 缺陷本质:断点是**纯宽度**的(<1024 都算窄屏)⇒ 竖屏 390 与横屏 844 落在同一档
* ⇒ 布局一个像素都不变,横屏多出来的宽度全浪费。看起来就是"没自适应"。
*
* 判据:横屏必须真的改变排布(并排),竖屏必须回到覆盖式,且来回切换都不坏。
* 用法AGENTMAIL_DIST=<dist> ADMIN_USER=.. ADMIN_PW=.. node test/manual/rotate-verify.mjs
*/
import { openApp } from './narrow-probe-helper.mjs';
const { page, ctx } = await openApp({ width: 390, height: 844 });
const results = [];
const record = (n, ok, note) => {
results.push({ n, ok });
console.log(` ${ok ? '通过' : '失败'} ${n}${note ? ' — ' + note : ''}`);
};
const snap = () =>
page.evaluate(() => {
const de = document.documentElement;
const content = document.querySelector('.narrow-shell > *:not(.narrow-nav)');
const nav = document.querySelector('.narrow-nav')?.getBoundingClientRect();
return {
vw: innerWidth,
vh: innerHeight,
appHeight: getComputedStyle(de).getPropertyValue('--app-height').trim(),
overflowX: de.scrollWidth - de.clientWidth,
contentCls: content ? content.className.toString().slice(0, 40) : '',
navVisible: nav ? nav.bottom <= innerHeight + 1 && nav.top > 0 : false,
navInset: nav ? Math.round(nav.left) : null
};
});
try {
await page.waitForSelector('.narrow-nav', { timeout: 25000 });
await page.waitForTimeout(1500);
const p1 = await snap();
record('竖屏覆盖式排布NarrowStack', /relative overflow-hidden/.test(p1.contentCls), p1.contentCls);
record('竖屏:--app-height 跟随视口', p1.appHeight === `${p1.vh}px`, `${p1.appHeight} vs ${p1.vh}`);
await page.setViewportSize({ width: 844, height: 390 });
await page.waitForTimeout(1300);
const l = await snap();
record('横屏:真的换了排布(并排,而不是原样)', /flex-1 min-h-0 flex$/.test(l.contentCls), l.contentCls);
record('横屏:--app-height 重算(旋屏后不是旧值)', l.appHeight === '390px', l.appHeight);
record('横屏:无横向溢出', l.overflowX <= 0, `溢出 ${l.overflowX}px`);
record('横屏:底部导航仍完整可见且浮着', l.navVisible && l.navInset >= 6, `left=${l.navInset}`);
await page.setViewportSize({ width: 390, height: 844 });
await page.waitForTimeout(1300);
const p2 = await snap();
record('旋回竖屏:恢复覆盖式(可逆)', /relative overflow-hidden/.test(p2.contentCls), p2.contentCls);
record('旋回竖屏:高度重算回 844', p2.appHeight === '844px', p2.appHeight);
} finally {
await page.close();
await ctx.close();
}
const failed = results.filter(r => !r.ok);
console.log(`\n 横竖屏自适应:${results.length - failed.length}/${results.length} 通过`);
if (failed.length) console.log(' 失败:' + failed.map(f => f.n).join('; '));
process.exitCode = failed.length ? 1 : 0;