* fix(ui): 去掉 html/body 的 overflow-x: hidden,恢复侧栏与页头吸顶 #1704 引入的 bg-global.css 给 html、body 加了 overflow-x: hidden,任何非 visible 的 overflow 都会把 body 变成滚动容器,侧栏(layout.module.scss .sider)和 PageHeader 的 position: sticky 于是相对 body 而不是视口定位——主内容一长, 整页滚动就把左侧导航和「保存」按钮一起顶出视口。 - 删除 html/body 的 overflow-x: hidden,并在两处样式注明这条约束 - 两个 position: fixed 的背景层改用 inset: 0 铺满视口,不再依赖 100vw, 也不会撑出横向滚动条 问题 1 of #1705(侧边导航被顶出)。 * fix(ui): 空间配置「平台设置」只保留左侧平台列表一套导航 #1704 把平台设置改成「左列平台列表 + 右栏 Collapse」后,右栏的手风琴仍然 为每个平台渲染一条带平台名的折叠栏,与左列重复(#1705 第二点)。 - 新增 app/ui/plugins/PlatformPanel.tsx:各平台插件的外壳,传入 bare 时只 输出字段,否则保持原来的 Collapse.Panel(配置覆写弹窗仍在用) - 10 个平台插件把 Collapse.Panel 换成 PlatformPanel,并透传 bare - dashboard 右栏不再用 Collapse,改为每个平台一个 <section hidden>:所有 字段始终挂载,只切换 hidden,保证 PUT /v1/configuration 整表覆盖时其他 平台的参数与凭据不会因为字段卸载而丢失 - 左列平台列表在页头下方吸顶(position: sticky),右栏面板很长时列表不再 随内容滚出视口;PageHeader 把自身高度写入 --page-header-height 供其取用; Tabs 关闭 tabPaneMotion 并放开 .semi-tabs-pane 的 overflow,否则 pane 会 成为 sticky 的滚动容器。移动端横排 chip 行保持随内容滚动 - 左列按钮补 aria-pressed,nav 补 aria-label Fixes #1705 * feat(ui): 空间配置保存校验失败时自动定位到第一个出错字段 平台设置的字段全部挂载、只切换 hidden,未选中的 Tab / 平台面板里的校验 错误用户看不到,表现为点「保存」没有任何反应。 - Form 加 onSubmitFail:把 Semi 的嵌套 errors 拍平成字段路径,按 DOM 顺序 找到第一个出错字段,切到它所在的 Tab(Tabs 改为受控)与平台面板,再 scrollIntoView 并聚焦,同时 Toast 提示未通过的项数 - TabPane 内容加 data-tab、平台 section 加 data-platform,供定位使用; 不改插件接口 Refs #1705 * refactor(ui): 改用应用壳布局解决侧栏被顶出,移除 sticky 补救与 tabPaneMotion 取舍 按 review 意见(#1706)不再靠 position: sticky 解决问题一,改成简单的应用壳: - layout.module.scss:.app 改为 height: 100vh(100dvh)+ overflow: hidden 的 flex 容器, 页面本身不滚动;.sider 是固定宽度的普通子元素(撑满壳高,去掉 sticky/top/100vh); .main 加 min-height: 0 + overflow: auto,成为唯一的滚动容器。侧栏、页脚服务灯 自然留在视口内,PageHeader 原有的 position: sticky 相对 .main 吸顶,无需改动 - 去掉为让平台列表在 Tab 面板内 sticky 而加的补救:.platformNav 的 sticky / --page-header-height / max-height、PageHeader 的 ResizeObserver、Tabs 的 tabPaneMotion={false} 以及 .semi-tabs-pane 的 overflow 覆盖,Tab 切换动画恢复。 平台列表改回随内容滚动 - bg-global.css:文档不再滚动,html/body 不需要 overflow 规则,注释改为说明现状; 两个 fixed 背景层保持 inset: 0 验证:tsc 0 错误、next build 通过;13 页 × 浅色 / 深色 / 折叠 / 移动端 390 / 平板 760, 主区滚到底后 document.scrollHeight == innerHeight(文档不滚)、aside top 0、页脚 bottom == innerHeight、header top 0、main 无横向溢出;Semi Select 下拉(主区预滚 1.2k px 及打开后继续滚动)、Popconfirm、配置覆写 Modal 及其内部 Select、Toast 位置全部正确; 切遍 10 个平台后保存 PUT 73/73 键(3 次);校验失败自动定位三场景通过(2 轮)。 Refs #1705 * refactor(ui): 平台设置去掉外层嵌套卡片,改两栏独立滚动布局 按 review 第二条意见(#1706):平台列表不用 sticky,也不随内容滚走——去掉包在 「平台列表 + 面板」外面的嵌套卡片,让两栏并排、各自独立滚动。 - dashboard/page.tsx:删掉 dc.content / rootConfigPanel / main / content 四层包裹和 平台设置里的 framePlatformConfig 卡片与重复的「平台设置」标题;页面主体改为 .page(占满页头以下的剩余高度)→ Form → Tabs,每个 Tab 面板在自己内部滚动, 页面本身不滚,页头「保存」始终可见。去掉底部两个 Space 占位 - dashboard.module.scss:重写。删除 #1704 之前遗留的整段 .rootConfigPanel 嵌套规则 (其中 frameInside / group / lineStory 等类早已无人引用);Form / Tabs / semi-tabs-content / semi-tabs-pane(含开启动画时的 motion-overlay)改为 flex: 1 + min-height: 0 的列容器,把高度让给当前面板,并补回 .semi-tabs-pane-inactive 的 display: none(本模块选择器特异性更高) - 平台设置:.platformLayout 两栏,.platformNav 160px、align-self: flex-start、 max-height: 100% + overflow-y: auto(矮视口时列表自己滚),.platformBody flex: 1 + overflow-y: auto。右栏再长列表也不动 - 全局设置 / 开发者选项一致处理:frameDownload / frameUpload / frameDeveloper 不再是 带边框和 50px 内边距的卡片,改为分区标题 + 分隔线的普通分区,面板 .pane 自身滚动 - 移动端(≤680px):两栏改为上下堆叠,平台列表是横向滑动的标签行,固定在面板顶部 不随字段滚走 - 自定义背景开启时给两个滚动面板垫一层 75% 的 bg-1 半透明底色,保证文字可读 验证:tsc 0 错误、next build 通过;空间配置页在 1440 / 760 / 390 × 浅 / 深 / 折叠 / 520px 矮视口下:文档与 <main> 均不滚动,页头与「保存」始终在视口内,右栏滚到底 (哔哩哔哩面板 1223px)时平台列表位置不变,矮视口下列表自身可滚;全局设置面板独立 滚动;切遍 10 个平台后保存 PUT 73/73 键(4 次);校验失败自动定位三场景通过(3 轮, scrollIntoView 在嵌套滚动容器内正常);Select 下拉在面板预滚 1k px 及滚动中跟随触发器, Popconfirm / Modal / Toast 位置正确;其余 12 页布局探针与上一提交一致。 Refs #1705 * fix(ui): 更新日志页内容不再覆盖导航顶栏 应用壳布局下页头真正吸顶后暴露出来的问题(review 第三条,#1706):更新日志页把 PageHeader 又包在一层 position: sticky; z-index: 1 的 Semi Layout.Header 里, 形成一个层级只有 1 的 stacking context,PageHeader 自己的 z-index: 10 只在这层 内部生效;而版本卡片流 .feed 又设了 position: relative; z-index: 1,DOM 顺序在 后,滚动时就画在页头之上。 - changelog/page.tsx:去掉外层 Header,与其它页一样直接渲染 PageHeader - changelog.module.scss:删掉 .feed / .center 的 position: relative; z-index: 1 验证:10 个带页头的页面滚到底后对页头内 6 个点做 elementFromPoint 命中测试, 全部命中页头自身(修前 /changelog 有 4 个点命中版本卡片头);/history 播放器 Modal 居中且在最上层;/logviewer、/status 等无层叠。 Refs #1705
146 lines
3.5 KiB
SCSS
146 lines
3.5 KiB
SCSS
/* 空间配置页
|
||
页头下方是 Tabs,每个 Tab 面板占满剩余高度并在自己内部滚动;
|
||
页面本身(应用壳的 .main)不滚动,页头的「保存」始终可见。 */
|
||
.page {
|
||
flex: 1;
|
||
min-height: 0;
|
||
display: flex;
|
||
flex-direction: column;
|
||
width: 100%;
|
||
max-width: 1280px;
|
||
margin: 0 auto;
|
||
box-sizing: border-box;
|
||
padding: 12px 28px 20px;
|
||
}
|
||
|
||
/* Semi 的 Form / Tabs 默认按内容撑开,这里让它们把剩余高度让给当前面板
|
||
(semi-tabs-pane-motion-overlay 是开启切换动画时 Semi 多包的一层) */
|
||
.form,
|
||
.tabs,
|
||
.tabs :global(.semi-tabs-content),
|
||
.tabs :global(.semi-tabs-pane),
|
||
.tabs :global(.semi-tabs-pane-motion-overlay) {
|
||
flex: 1;
|
||
min-height: 0;
|
||
display: flex;
|
||
flex-direction: column;
|
||
}
|
||
.tabs :global(.semi-tabs-content) {
|
||
padding: 0;
|
||
}
|
||
/* 上面的 display: flex 特异性高于 Semi 自己的 .semi-tabs-pane-inactive,未选中的面板要补回隐藏 */
|
||
.tabs :global(.semi-tabs-pane-inactive) {
|
||
display: none;
|
||
}
|
||
|
||
/* 全局设置 / 开发者选项:面板自身滚动 */
|
||
.pane {
|
||
flex: 1;
|
||
min-height: 0;
|
||
overflow-y: auto;
|
||
padding: 16px 4px 32px;
|
||
}
|
||
|
||
/* 表单分区:不再套卡片,只用分区标题 + 分隔线区分 */
|
||
.frameDownload,
|
||
.frameUpload,
|
||
.frameDeveloper {
|
||
display: flex;
|
||
flex-direction: column;
|
||
row-gap: 10px;
|
||
}
|
||
.frameUpload {
|
||
margin-top: 24px;
|
||
padding-top: 24px;
|
||
border-top: 1px solid var(--semi-color-border);
|
||
}
|
||
|
||
/* 平台设置:左列平台列表 + 右栏选中平台的字段。两栏并排、各自独立滚动,
|
||
右栏再长,列表也不会跟着滚走 */
|
||
.platformLayout {
|
||
flex: 1;
|
||
min-height: 0;
|
||
display: flex;
|
||
gap: 16px;
|
||
padding-top: 16px;
|
||
}
|
||
.platformNav {
|
||
width: 160px;
|
||
flex-shrink: 0;
|
||
align-self: flex-start;
|
||
max-height: 100%;
|
||
box-sizing: border-box;
|
||
overflow-y: auto;
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 4px;
|
||
padding: 4px;
|
||
background: var(--semi-color-fill-0);
|
||
border-radius: 8px;
|
||
}
|
||
.platformNavItem {
|
||
appearance: none;
|
||
border: none;
|
||
text-align: left;
|
||
cursor: pointer;
|
||
padding: 8px 12px;
|
||
border-radius: 6px;
|
||
font-size: 13px;
|
||
color: var(--semi-color-text-1);
|
||
background: transparent;
|
||
transition: background 0.15s ease, color 0.15s ease;
|
||
}
|
||
.platformNavItem:hover {
|
||
background: var(--semi-color-fill-1);
|
||
color: var(--semi-color-text-0);
|
||
}
|
||
.platformNavItemActive,
|
||
.platformNavItemActive:hover {
|
||
background: var(--semi-color-primary);
|
||
color: var(--semi-color-white);
|
||
}
|
||
.platformBody {
|
||
flex: 1;
|
||
min-width: 0;
|
||
min-height: 0;
|
||
overflow-y: auto;
|
||
padding-bottom: 32px;
|
||
}
|
||
/* 右栏:只显示选中平台的字段;不设 display,以免覆盖 hidden 属性 */
|
||
.platformPanel {
|
||
padding: 4px 16px 8px 8px;
|
||
}
|
||
|
||
/* 自定义背景开启时表单直接铺在背景图上,给滚动面板垫一层半透明底色保证可读 */
|
||
:global(body.app-has-bg) .pane,
|
||
:global(body.app-has-bg) .platformBody {
|
||
background: color-mix(in srgb, var(--semi-color-bg-1) 75%, transparent);
|
||
border-radius: 12px;
|
||
}
|
||
|
||
/* 移动端:两栏改为上下堆叠,平台列表变成横向滑动的标签行,仍不随内容滚走 */
|
||
@media (max-width: 680px) {
|
||
.page {
|
||
padding: 8px 12px 12px;
|
||
}
|
||
.platformLayout {
|
||
flex-direction: column;
|
||
gap: 10px;
|
||
padding-top: 10px;
|
||
}
|
||
.platformNav {
|
||
width: 100%;
|
||
max-height: none;
|
||
align-self: stretch;
|
||
flex-direction: row;
|
||
overflow-x: auto;
|
||
overflow-y: hidden;
|
||
}
|
||
.platformNavItem {
|
||
white-space: nowrap;
|
||
}
|
||
.platformPanel {
|
||
padding: 4px 4px 8px;
|
||
}
|
||
}
|