修复虚拟列表卡片区空白:页面高度按父级实测
Project CI / AI game creator shell Rust shard 1/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 2/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 3/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 4/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust smoke (pull_request) Has been cancelled
Project CI / AI game creator shell Rust crates (pull_request) Has been cancelled
Project CI / Backend tests (pull_request) Has been cancelled
Project CI / Native shell tests (pull_request) Has been cancelled
Project CI / Frontend tests (pull_request) Has been cancelled
Project CI / Repository checks (pull_request) Has been cancelled
Project CI / AI game creator shell web tests (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 1/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 2/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 3/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 4/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust smoke (pull_request) Has been cancelled
Project CI / AI game creator shell Rust crates (pull_request) Has been cancelled
Project CI / Backend tests (pull_request) Has been cancelled
Project CI / Native shell tests (pull_request) Has been cancelled
Project CI / Frontend tests (pull_request) Has been cancelled
Project CI / Repository checks (pull_request) Has been cancelled
Project CI / AI game creator shell web tests (pull_request) Has been cancelled
- 页面根节点高度改为内联写入父级 .launcher-main 的实测高度:外壳的 .launcher-main > .platform-theme { height:100% } 特异性高于 Tailwind,且该百分比在 min-height:100vh 链上是不定高,页面退化成内容高度后虚拟网格视口为 0(卡片区整片空白);100vh 又比舞台高一个标题栏会裁掉底部
- 技术方案补页面高度契约说明
- 真机复测(1000 条假数据):可视区 16 张卡、进入页面后 23ms 出现卡片、搜索到空态 22ms、清空搜索回全量 22ms;WebView2 组工作集 487MB(修复前 4.2-4.6GB)
This commit is contained in:
@@ -135,6 +135,8 @@ export default function TemplateLibraryView({
|
||||
|
||||
const gridRef = useRef<FixedSizeGrid>(null);
|
||||
const viewportRef = useRef<HTMLDivElement | null>(null);
|
||||
const sectionRef = useRef<HTMLElement | null>(null);
|
||||
const [sectionHeight, setSectionHeight] = useState<number | null>(null);
|
||||
const [viewportSize, setViewportSize] = useState({ width: 0, height: 0 });
|
||||
|
||||
const showEmptyLibrary = status === 'ready' && templates.length === 0;
|
||||
@@ -142,6 +144,36 @@ export default function TemplateLibraryView({
|
||||
status === 'ready' && templates.length > 0 && visibleTemplates.length === 0;
|
||||
const showGrid = status === 'ready' && visibleTemplates.length > 0;
|
||||
|
||||
/**
|
||||
* 页面高度按**父级实测高度**定,不用百分比也不用 100vh。
|
||||
*
|
||||
* 外壳样式 `.launcher-main > .platform-theme { height: 100% }` 特异性高于 Tailwind
|
||||
* 工具类,而它的百分比在 `.launcher-shell { min-height: 100vh }` 这条链上是不定高,
|
||||
* 页面会退化成内容高度(虚拟网格视口高度 0、卡片区空白);`100vh` 又比真实舞台高
|
||||
* 一个标题栏(窗口 100vh=800、舞台 750),底部会被裁掉。这里直接量父级。
|
||||
*/
|
||||
useEffect(() => {
|
||||
const section = sectionRef.current;
|
||||
const parent = section?.parentElement;
|
||||
if (!section || !parent) {
|
||||
return;
|
||||
}
|
||||
const apply = () => {
|
||||
const height = Math.round(parent.getBoundingClientRect().height);
|
||||
if (height > 0) {
|
||||
setSectionHeight((current) => (current === height ? current : height));
|
||||
}
|
||||
};
|
||||
apply();
|
||||
if (typeof ResizeObserver === 'undefined') {
|
||||
window.addEventListener('resize', apply);
|
||||
return () => window.removeEventListener('resize', apply);
|
||||
}
|
||||
const observer = new ResizeObserver(apply);
|
||||
observer.observe(parent);
|
||||
return () => observer.disconnect();
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
const element = viewportRef.current;
|
||||
if (!element) {
|
||||
@@ -216,7 +248,9 @@ export default function TemplateLibraryView({
|
||||
|
||||
return (
|
||||
<section
|
||||
className="platform-theme platform-theme--light flex h-full min-h-0 w-full flex-col gap-3.5 overflow-hidden px-6 pb-5 pt-5 max-[760px]:px-4"
|
||||
ref={sectionRef}
|
||||
style={sectionHeight ? { height: `${sectionHeight}px` } : undefined}
|
||||
className="platform-theme platform-theme--light flex min-h-0 w-full flex-col gap-3.5 overflow-hidden px-6 pb-5 pt-5 max-[760px]:px-4"
|
||||
aria-label="模板库"
|
||||
>
|
||||
<header className="flex flex-wrap items-center gap-3">
|
||||
|
||||
@@ -102,6 +102,7 @@ AGC_TEMPLATE_LIBRARY_SYNTHETIC_COUNT=300 AGC_DEV_CARGO_FEATURES=template-library
|
||||
- 列表改用 workspace 里已有的 `react-window@1.8.11` 的 `FixedSizeGrid`(`react-arborist` 已在用同一版本,不引入新包;类型来自 devDependency `@types/react-window`)。
|
||||
- 布局契约收在纯函数 `templateLibraryGrid.ts`(单测覆盖):列数 = `floor((容器宽 + gap) / (最小卡宽 + gap))`、列宽 = 容器宽 / 列数、行高 = `卡片宽 × 9/16 + 文字区 150 + gap`;`buildTemplateRows` 按行切分并在行尾补 `null` 占位。
|
||||
- 卡片抽成 `TemplateCard`(`memo`),网格只渲染可视行 + 2 行 overscan;筛选条件(关键词/标签/运行时/仅看已下载)变化时把滚动位置复位到顶部,避免"从筛选切回全量后停在空白处"。
|
||||
- **页面高度契约**:页面根节点的高度按**父级 `.launcher-main` 的实测高度**内联设置,既不用百分比也不用 `100vh`。原因:外壳样式 `.launcher-main > .platform-theme { height: 100% }` 特异性高于 Tailwind 工具类,而这条百分比在 `.launcher-shell { min-height: 100vh }` 链路上是不定高,页面会退化成内容高度(虚拟网格视口高度 0、卡片区整片空白);`100vh` 又比真实舞台高一个标题栏高度(窗口 100vh=800 / 舞台 750),底部会被裁掉。
|
||||
- 筛选区(运行时/标签)改成可独立滚动的区块(`max-h-[24vh]`),标签数量随库量增长时不再把卡片区挤出窗口。
|
||||
- 回归:`templateLibraryGrid.test.ts` 覆盖列数/行高/行数/切行;页面测试用固定视口断言「1000 条只渲染 ≤ 40 张卡片,滚动高度仍按 250 行计算」。
|
||||
|
||||
|
||||
Reference in New Issue
Block a user