style: 修复侧栏分类圆角,顶部增加软虚化

- nav-card 补 12px 圆角与 overflow hidden
- 搜索框 50% 透明 + blur(14px)
- 新增 top-blur:blur(8px) + 上下 mask 渐隐,覆盖搜索与内容顶部,不出现硬线
- 验证:nav 圆角 12、搜索可点、虚化生效
This commit is contained in:
2026-10-31 17:03:20 +08:00
parent 2a344ae534
commit 762de4a4e1
4 changed files with 48 additions and 3 deletions
+1 -1
View File
@@ -167,7 +167,7 @@ GET /api/backup SQLite 快照附件 需登录
- 当前 `PRAGMA user_version = 22`;`schema::migrate` 逐级升级:0 建全量、15→16→17→18→19→20→21→22、更高版本拒绝启动。 - 当前 `PRAGMA user_version = 22`;`schema::migrate` 逐级升级:0 建全量、15→16→17→18→19→20→21→22、更高版本拒绝启动。
- 格式在 `entry.format`(apps / posters / articles),同组可混合;`node` 的旧 `view_mode` 仅保留兼容,不再决定渲染。 - 格式在 `entry.format`(apps / posters / articles),同组可混合;`node` 的旧 `view_mode` 仅保留兼容,不再决定渲染。
- `settings.sidebar.show_profile / show_service` 控制侧栏两张卡片显隐(默认 true)。 - `settings.sidebar.show_profile / show_service` 控制侧栏两张卡片显隐(默认 true)。
- 首页滚动:`#page-scroll`(Layout 的 body)是唯一滚动容器,搜索框固定在其上方;左右两栏顶部对齐,左侧到底后通过 `translateY` 吸底,右侧继续滚动;滚动条隐藏;页头实底,搜索框悬浮,顶部与内容之间没有独立填充块。 - 首页滚动:`#page-scroll`(Layout 的 body)是唯一滚动容器,搜索框固定在其上方;左右两栏顶部对齐,左侧到底后通过 `translateY` 吸底,右侧继续滚动;滚动条隐藏;页头实底,搜索框 50% 透明,顶部另有一层上下渐隐的软虚化(`blur(8px)`)。
- 本地服务是运行时卡片,但 `card` 表里有一行 `local-service` 只用于排序;内容来自 `/api/projects`,后端禁止删除/改名/配置分组。 - 本地服务是运行时卡片,但 `card` 表里有一行 `local-service` 只用于排序;内容来自 `/api/projects`,后端禁止删除/改名/配置分组。
- `node` 是统一分组树(根节点 `kind='section'`,子节点 `kind='group'` 可多层);`enabled` 控制启停;`icon` 可为空。 - `node` 是统一分组树(根节点 `kind='section'`,子节点 `kind='group'` 可多层);`enabled` 控制启停;`icon` 可为空。
- 主要表:`node`、`entry`、`entry_tag`、`section_block`、`admin`、`session`、`setting`、`audit`。 - 主要表:`node`、`entry`、`entry_tag`、`section_block`、`admin`、`session`、`setting`、`audit`。
+7
View File
@@ -147,6 +147,13 @@ DELETE /api/items/:id
## 11. 实施记录 ## 11. 实施记录
### P27(2026-10-31,分类块圆角与顶部软虚化)
- 侧栏导航 `.nav-card` 是普通 div(不是 Card),之前没有圆角;补 `border-radius: 12px` + `overflow: hidden`,和资料/服务卡一致;
- 搜索框透明度提到 50%,模糊提到 14px;
- 新增 `.top-blur`:固定在 header 下方(top 60、height 120),`blur(8px)` + 18% 页面色渐变,并用上下 `mask-image` 渐隐,避免再次出现分割线;
- 验证:nav 圆角 12px、top-blur 存在且 blur 生效、搜索框仍可点击、滚动时顶部软虚化无硬边。
### P26(2026-10-31,顶部留白加高) ### P26(2026-10-31,顶部留白加高)
- 首页顶部偏移 `TOP_OFFSET` 从 88 调到 104,搜索框与内容卡片之间的空白从 28px 增加到 44px; - 首页顶部偏移 `TOP_OFFSET` 从 88 调到 104,搜索框与内容卡片之间的空白从 28px 增加到 44px;
+32 -2
View File
@@ -151,8 +151,33 @@
/* 搜索框半透明,顶部区域透出背景 */ /* 搜索框半透明,顶部区域透出背景 */
.search-row > *:first-child { .search-row > *:first-child {
background-color: color-mix(in srgb, var(--su-bg-card) 60%, transparent); background-color: color-mix(in srgb, var(--su-bg-card) 50%, transparent);
backdrop-filter: blur(10px); backdrop-filter: blur(14px);
}
/* 搜索区域软虚化:上下都用 mask 渐隐,不出现横向分割线 */
.top-blur {
position: fixed;
top: 60px;
right: 0;
left: 0;
z-index: 4;
height: 120px;
pointer-events: none;
background: linear-gradient(
to bottom,
color-mix(in srgb, var(--su-bg-page) 22%, transparent) 0%,
transparent 80%
);
backdrop-filter: blur(8px);
mask-image: linear-gradient(to bottom, transparent 0%, #000 28%, #000 62%, transparent 100%);
-webkit-mask-image: linear-gradient(
to bottom,
transparent 0%,
#000 28%,
#000 62%,
transparent 100%
);
} }
/* ---------- 两栏骨架 ---------- */ /* ---------- 两栏骨架 ---------- */
@@ -1339,6 +1364,11 @@ a.entry-href:hover {
backdrop-filter: blur(14px) saturate(1.15); backdrop-filter: blur(14px) saturate(1.15);
} }
.sidebar-home .nav-card {
overflow: hidden;
border-radius: var(--su-radius-md);
}
.sidebar-divider { .sidebar-divider {
margin: var(--su-space-2) 0; margin: var(--su-space-2) 0;
border-top: 1px dashed var(--su-border-strong); border-top: 1px dashed var(--su-border-strong);
+8
View File
@@ -223,6 +223,13 @@ export default function AppNext() {
const onScroll = () => setScrolled(body.scrollTop > 4) const onScroll = () => setScrolled(body.scrollTop > 4)
// 顶部软虚化层:覆盖搜索区域与内容顶部,边缘用 mask 渐隐,避免硬分割线
const blur = document.createElement('div')
blur.className = 'top-blur'
blur.setAttribute('aria-hidden', 'true')
const appRoot = document.querySelector('.app')
appRoot?.appendChild(blur)
const updateSticky = () => { const updateSticky = () => {
const viewport = body.clientHeight const viewport = body.clientHeight
const maxLeft = Math.max(0, sider instanceof HTMLElement ? sider.offsetHeight - viewport : 0) const maxLeft = Math.max(0, sider instanceof HTMLElement ? sider.offsetHeight - viewport : 0)
@@ -246,6 +253,7 @@ export default function AppNext() {
body.removeEventListener('scroll', updateSticky) body.removeEventListener('scroll', updateSticky)
window.removeEventListener('resize', updateSticky) window.removeEventListener('resize', updateSticky)
observer.disconnect() observer.disconnect()
blur.remove()
body.id = '' body.id = ''
body.style.overflowY = '' body.style.overflowY = ''
body.style.overflowX = '' body.style.overflowX = ''