diff --git a/client/electron/src/components/CalendarView.tsx b/client/electron/src/components/CalendarView.tsx index a5033c9..0338811 100644 --- a/client/electron/src/components/CalendarView.tsx +++ b/client/electron/src/components/CalendarView.tsx @@ -447,7 +447,9 @@ export default function CalendarView() { } return ( -
+ /* `cal-panes`:这一层是"拼成一张卡的两块面板",圆角规则在 index.css 里 + (根节点自己没有底色,见那里的说明)*/ +
{gridPane}
{sidePane} diff --git a/client/electron/src/index.css b/client/electron/src/index.css index 57c9845..53f7505 100644 --- a/client/electron/src/index.css +++ b/client/electron/src/index.css @@ -1127,6 +1127,38 @@ html.view-switch .glass-control, min-height: 0; } +/* + * ★ 日历:网格栏与右栏拼成**一张卡**(中间是分隔线,不是外壳间距) + * 用户(2026-09-14):「日历页面还没有添加圆角」。 + * + * 为什么它一直没圆角:外壳那条 `.app-shell > *` 的圆角加在日历**根节点**上, + * 而根节点是 `flex-1 min-w-0 flex min-h-0` —— **它自己没有底色**。 + * 真正白底的是里面那两块面板,直角从透明外壳里戳出来,看上去就是没圆角。 + * + * 两个不能照搬收件箱做法的地方: + * + * ① 这两块面板**不是两张卡**(中间只有 1px 分隔线、没有外壳间距), + * 所以只能给**外沿**:左边那块给左两角、右边那块给右两角。 + * 内侧要是也圆了,分隔线两边会露出底色缺口。 + * ② 右栏外面还套了一层容器(管宽度 `lg:w-[400px]` 与 `border-l`,自己不上色), + * 真正上色的是它里面的 DayAgendaPane / CalendarEventEditor。 + * 圆角只加在容器上会被内层的直角**原地盖掉** —— 所以要再往下给一层。 + * (左栏本身就是白底面板,不能再往下给:它的第一个子元素是工具条, + * 给下去变成"工具条圆角",那不是我们要的东西。) + */ +.cal-panes > :first-child { + border-start-start-radius: var(--radius-card); + border-end-start-radius: var(--radius-card); + background-clip: padding-box; +} + +.cal-panes > :last-child, +.cal-panes > :last-child > * { + border-start-end-radius: var(--radius-card); + border-end-end-radius: var(--radius-card); + background-clip: padding-box; +} + /* * 桌面侧栏:无论有没有壁纸都做深色玻璃 —— 否则它是全页唯一一块实心黑。 diff --git a/client/electron/test/manual/wide-regression.mjs b/client/electron/test/manual/wide-regression.mjs index f882bb0..1443b26 100644 --- a/client/electron/test/manual/wide-regression.mjs +++ b/client/electron/test/manual/wide-regression.mjs @@ -19,7 +19,14 @@ const chk = (n, ok, note = '') => { console.log('宽屏回归(1280px):'); const cols = await page.evaluate(() => { - const root = document.querySelector('#root > div'); + /* + * 选 `.app-shell`,不是 `#root > div`。 + * + * 壁纸层(`app-backdrop`)后来挂成了 `#root` 的第一个子节点,`#root > div` + * 从此指向**幕布本身**(它没有子节点)—— 这条判据于是一直报「栏数=0」的假失败。 + * 假失败比没有判据更贵:看的人会去查一个本来好好的三栏布局。 + */ + const root = document.querySelector('.app-shell'); return { n: root?.children.length, first: root?.children[0]?.className?.toString().slice(0, 30) }; }); chk('仍是三栏并排', cols.n === 3, `栏数=${cols.n} 首栏=${cols.first}`); @@ -124,6 +131,53 @@ await page.locator('[data-testid="reply-fab"]').click(); await page.waitForTimeout(500); chk('宽屏点悬浮球能展开输入框(带焦点)', await page.evaluate(() => document.activeElement?.tagName === 'TEXTAREA')); +/* + * 日历的圆角(用户 2026-09-14:「日历页面还没有添加圆角」)。 + * + * 为什么在这里验、而不是只验 CSS:那一族的形态是**「computed style 里 + * border-radius 就是 14px,看上去却是方角」** —— 圆角加在一个**没有底色**的 + * 外层上,白底的内层面板用直角原地把它盖掉了。 + * 光看 `getComputedStyle(panel).borderRadius` 也区分不了:真正决定观感的是 + * **角上那 2px 到底是谁在画**。所以从 elementFromPoint 起往上走,找第一个 + * 自带底色的元素 —— 它必须就是那个圆角面板本身。 + */ +await page.locator('button:has-text("日历")').first().click(); +await page.waitForSelector('.cal-panes', { timeout: 20000 }); +await page.waitForTimeout(600); +const cal = await page.evaluate(() => { + const w = document.querySelector('.cal-panes'); + if (!w) return { found: false }; + const first = w.firstElementChild; + const last = w.lastElementChild; + const lastInner = last.firstElementChild; + const painterAt = (x, y) => { + let e = document.elementFromPoint(x, y); + while (e) { + const bg = getComputedStyle(e).backgroundColor; + if (bg && bg !== 'rgba(0, 0, 0, 0)' && bg !== 'transparent') return e; + e = e.parentElement; + } + return null; + }; + const rf = first.getBoundingClientRect(); + const rl = last.getBoundingClientRect(); + return { + found: true, + firstRadius: getComputedStyle(first).borderRadius, + lastRadius: lastInner ? getComputedStyle(lastInner).borderRadius : null, + tl: painterAt(rf.x + 2, rf.y + 2) === first, + bl: painterAt(rf.x + 2, rf.bottom - 3) === first, + tr: painterAt(rl.right - 3, rl.y + 2) === lastInner, + br: painterAt(rl.right - 3, rl.bottom - 3) === lastInner + }; +}); +chk('日历布局挂上了面板栈标记', cal.found); +chk( + '日历四个外角由**自带底色的那层面板**画(不是透明外壳)', + cal.found && cal.tl && cal.bl && cal.tr && cal.br, + `左栏 radius=${cal.firstRadius} 右栏 radius=${cal.lastRadius} 角=${JSON.stringify({ tl: cal.tl, bl: cal.bl, tr: cal.tr, br: cal.br })}` +); + console.log('\nissues:', issues.length ? issues : '无'); console.log(failed.length === 0 ? '\n宽屏回归:全部通过' : `\n宽屏回归:${failed.length} 项失败`); diff --git a/client/electron/test/narrow-layout.test.mjs b/client/electron/test/narrow-layout.test.mjs index 83550eb..fc05bbe 100644 --- a/client/electron/test/narrow-layout.test.mjs +++ b/client/electron/test/narrow-layout.test.mjs @@ -213,6 +213,43 @@ check( (maskRule.match(/-webkit-mask-image:/g) || []).length === 1 && (maskRule.match(/[^-]mask-image:/g) || []).length === 1 ); + +// 5.10) 面板圆角必须给到**有底色的那一层**。 +// +// 用户(2026-09-14):「日历页面还没有添加圆角」。 +// +// 这一族的形态最骗人:`getComputedStyle` 里 `border-radius` **就是 14px** +// (外壳那条 `.app-shell > *` 确实加上了),可**看上去是方角** —— +// 因为外壳节点是 `flex-1 min-w-0 flex min-h-0`、**自己没有底色**, +// 真正白底的是里面那两块面板,它们的直角从透明外壳里戳出来。 +// 所以判据不能只查「有没有 border-radius」,要钉住: +// ① 规则与 JSX 是否真接上了(两张表按**类名**联接,不按相邻关系); +// ② 给的是**哪几条边**; +// ③ 中间那层容器自己不上色时,圆角得**再往下给一层**。 +const cal = read('../src/components/CalendarView.tsx'); +const calFirst = (css.match(/\.cal-panes\s*>\s*:first-child\s*\{[\s\S]*?\n\}/) || [''])[0]; +const calLast = (css.match(/\.cal-panes\s*>\s*:last-child[\s\S]*?\n\}/) || [''])[0]; +check( + '日历根节点挂上了面板栈标记(CSS 选择器与 JSX 类名接得上)', + calFirst !== '' && /className="cal-panes[ "]/.test(cal), + 'CSS 里有规则但 JSX 没挂类名(或反之)—— 两边各自看都“有”,圆角却不生效' +); +check( + '日历外沿两角分两侧给:首元素给起始两角、末元素给结束两角', + /border-start-start-radius/.test(calFirst) && /border-end-start-radius/.test(calFirst) && + /border-start-end-radius/.test(calLast) && /border-end-end-radius/.test(calLast), + '这两块面板中间是**分隔线**不是外壳间距:四角全给会在分隔线两边露出底色缺口' +); +check( + '右栏容器里面的面板也拿到圆角(否则内层直角把圆角原地盖掉)', + /\.cal-panes\s*>\s*:last-child\s*>\s*\*/.test(css), + '右栏外面那层只管宽度与分隔线、自己不上色 —— 只给这层加圆角=无效果' +); +check( + '左栏规则直接落在面板本身(不再往下给)', + calFirst !== '' && !/\.cal-panes\s*>\s*:first-child\s*>\s*\*/.test(css), + '左栏本身就是白底面板;再往下就给到了第一个子元素(工具条),圆到不该圆的东西上' +); check('根视口使用 100dvh 跟随软键盘', css.includes('@supports (height: 100dvh)')); // 6) 横向内边距在窄屏收窄(px-6 在 375px 屏上白吃 48px) diff --git a/client/electron/test/run-all.mjs b/client/electron/test/run-all.mjs index 58a34f5..0118c64 100644 --- a/client/electron/test/run-all.mjs +++ b/client/electron/test/run-all.mjs @@ -58,7 +58,7 @@ for (const must of ['配对/解析', 'allow-list', '变异验证', '剥掉注释 const SUITE = [ ['test/markdown-xss.test.mjs', [], 9], - ['test/narrow-layout.test.mjs', [], 58], + ['test/narrow-layout.test.mjs', [], 62], ['test/nav-merge.test.mjs', [], 8], ['test/theme.test.mjs', [], 30], ['test/background.test.mjs', [], 42],