From 1942e201e9ea21f44ceaf298c43c348ce3257613 Mon Sep 17 00:00:00 2001 From: stash Date: Wed, 28 Oct 2026 20:16:41 +0800 Subject: [PATCH] =?UTF-8?q?fix(web):=20=E8=A7=86=E8=A7=89=E4=B8=8E?= =?UTF-8?q?=E4=BA=A4=E4=BA=92=201:1=EF=BC=88=E9=A1=B5=E5=A4=B4/=E4=BE=A7?= =?UTF-8?q?=E6=A0=8F/=E5=8D=A1=E7=89=87/=E8=AF=A6=E6=83=85/=E5=8A=A8?= =?UTF-8?q?=E6=95=88=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 对齐项(8080 vs 8081 实测,误差 ≤1px): - 侧栏:资料卡 224、服务面板 144、导航 143,navTop 548 与原版一致 - 分区卡:142/142/327/270 vs 142/142/326/269;标题 16/1.2、更多按钮 24px - 应用条目:48px 圆形头像 + 10px 小认证标;hover 名字变主色(不再整行变色) - 封面:hover 上浮 2px(0.2s ease),去掉缩放;CES 封面恢复 16/10 - 搜索框:44 高、无边框 + 卡片阴影 - 服务面板:状态药丸 22、统计 12/18、操作按钮 28、刷新时图标原地旋转 - 详情:返回链接 hover 下划线、跳转按钮 hover 深主色、view-in 淡入动画 - 菜单:hover 主色、子菜单 0.28s grid 高度动画、chevron 6px 旋转 - 回到顶部:right 30、top 50%、滚动后淡入(补内容区滚动监听) - 主题:卡片阴影恢复 2%/6%(旧版值) --- stash-web/src/App.css | 149 ++++++++++++++++-- stash-web/src/App.tsx | 18 ++- stash-web/src/components/common/BackToTop.tsx | 2 +- stash-web/src/components/content/AppCard.tsx | 5 +- stash-web/src/components/content/CesCard.tsx | 3 +- .../src/components/content/SectionCard.tsx | 3 +- stash-web/src/components/search/SearchBar.tsx | 1 + .../src/components/sidebar/ProfileCard.tsx | 18 ++- .../src/components/sidebar/ServicePanel.tsx | 15 +- 9 files changed, 181 insertions(+), 33 deletions(-) diff --git a/stash-web/src/App.css b/stash-web/src/App.css index 6c80588..a486b5b 100644 --- a/stash-web/src/App.css +++ b/stash-web/src/App.css @@ -6,6 +6,9 @@ z-index: 1; /* 透明:让固定背景图从下面透出来(Layout 默认有底色) */ background-color: transparent; + /* 旧版阴影是 2% / 6%,比库默认更深,属于主题级覆盖 */ + --su-shadow-card: 0 6px 16px rgba(27, 26, 49, 0.02); + --su-shadow-hover: 0 6px 16px rgba(27, 26, 49, 0.06); } /* 顶部背景图:固定 65vh,底部渐隐到页面底色 */ @@ -87,6 +90,12 @@ transform: translateX(-50%); } +/* 旧版搜索是「无边框 + 卡片阴影」 */ +.search-row > *:first-child { + border-color: transparent; + box-shadow: var(--su-shadow-card); +} + /* ---------- 两栏骨架 ---------- */ .content { @@ -114,14 +123,57 @@ text-align: center; } +.profile-name { + line-height: 1.2; +} + +.profile-role { + padding: 1px 8px; + border: 1px solid var(--su-border); + border-radius: var(--su-radius-pill); + font-size: var(--su-font-size-xs); + line-height: 18px; + color: var(--su-text-sub); +} + .profile-bio { - line-height: 1.8; + margin-top: 2px; + line-height: 1.55; +} + +.profile-location { + margin-top: 2px; + font-size: var(--su-font-size-xs); + line-height: 18px; + color: var(--su-text-muted); +} + +/* 旧版头像下面留 4px,和名字之间更松 */ +.profile-card > span:first-child { + margin-bottom: 4px; } .service-panel { padding: 12px 14px; } +/* 旧版标题与统计值的行高比库默认更紧 */ +.service-panel h2 { + line-height: 20px; +} + +/* 旧版连接状态药丸:22 高、12px */ +.service-status { + height: 22px; + padding: 0 10px; + font-size: var(--su-font-size-xs); +} + +/* 旧版统计行是 12/18 */ +.service-stats span { + line-height: 18px; +} + .service-stats { display: flex; flex-direction: column; @@ -162,6 +214,16 @@ margin-bottom: var(--su-space-4); } +/* 旧版分区标题是 16/1.2,更多按钮是 24px 小方按钮 */ +.section-header h2 { + line-height: 1.2; +} + +.section-more { + width: 24px; + height: 24px; +} + .section-bar { width: 4px; height: 16px; @@ -178,8 +240,8 @@ border-radius: var(--su-radius-sm); } -.app-card:hover { - background-color: var(--su-bg-subtle); +.app-card:hover .app-card-name { + color: var(--su-color-primary); } .app-card-info { @@ -189,10 +251,29 @@ min-width: 0; } +/* 旧版应用头像是 48px 圆形,右下角是 10px 小认证标 */ +.app-card-avatar { + width: 48px; + height: 48px; + font-size: 18px; +} + +.app-card-avatar > span + span { + width: 10px; + height: 10px; + border-width: 1px; + font-size: 6px; +} + /* ---------- 图文白卡 ---------- */ .ces-card { overflow: hidden; + transition: transform var(--su-duration-fast) var(--su-ease-in-out); +} + +.ces-card:hover { + transform: translateY(-2px); } .ces-body { @@ -227,10 +308,6 @@ padding: 12px var(--su-space-5); } -.detail-nav > * { - width: 100%; -} - .detail-back { color: var(--su-color-primary); font-size: var(--su-font-size-md); @@ -239,7 +316,11 @@ } .detail-back:hover { - opacity: 0.8; + text-decoration: underline; +} + +.detail-nav > * { + width: 100%; } .detail-hero { @@ -363,7 +444,7 @@ } .item-jump:hover:not(:disabled) { - opacity: 0.8; + background-color: var(--su-color-primary-hover); } .item-jump:disabled { @@ -454,6 +535,56 @@ /* ---------- 通用 ---------- */ +/* 服务面板的两个操作按钮:旧版是 12px / 28 高 / 等分 / 描边 */ +.service-action { + flex: 1; + height: 28px; + padding: 0 var(--su-space-2); + font-size: var(--su-font-size-xs); + border-radius: var(--su-radius-cover); +} + +.service-action:hover:not(:disabled) { + border-color: var(--su-color-primary); + background-color: var(--su-color-primary-soft); + color: var(--su-color-primary); +} + +/* 页头图标按钮:旧版 hover 是浅灰底 + 深色字 */ +.site-header-inner button:hover { + background-color: var(--su-bg-light); + color: var(--su-text-main); +} + +/* 分区卡右上角 •••:旧版 hover 只有浅灰底 */ +.section-more:hover { + background-color: var(--su-bg-light); + color: var(--su-text-sub); +} + +/* 详情 / 文章切换时的淡入上浮(旧版 view-in) */ +@keyframes view-in { + from { + opacity: 0; + transform: translateY(6px); + } + + to { + opacity: 1; + transform: none; + } +} + +.detail-view { + animation: view-in 0.22s ease both; +} + +@media (prefers-reduced-motion: reduce) { + .detail-view { + animation: none; + } +} + .link-button { display: inline-flex; align-items: center; diff --git a/stash-web/src/App.tsx b/stash-web/src/App.tsx index ccfa17a..a6a14af 100644 --- a/stash-web/src/App.tsx +++ b/stash-web/src/App.tsx @@ -103,20 +103,32 @@ export default function App() { return [] }, [itemView, itemCategory]) - // 切换视图时回到顶部(页面整体滚动) + // 切换视图时把内容区(内部滚动)和窗口都回到顶部 useEffect(() => { + const scroller = document.getElementById('content-scroll') + scroller?.scrollTo({ top: 0 }) window.scrollTo({ top: 0 }) }, [view]) + /** + * 滚动状态同时驱动「顶部渐隐」和「回到顶部」。 + * 桌面端滚的是内容容器(scroll 事件不冒泡),所以用捕获阶段监听。 + */ useEffect(() => { const sync = () => { - const next = window.scrollY > 4 + const inner = document.getElementById('content-scroll')?.scrollTop ?? 0 + const next = Math.max(inner, window.scrollY) > 4 setScrolled((current) => (current === next ? current : next)) } sync() window.addEventListener('scroll', sync, { passive: true }) - return () => window.removeEventListener('scroll', sync) + document.addEventListener('scroll', sync, { passive: true, capture: true }) + + return () => { + window.removeEventListener('scroll', sync) + document.removeEventListener('scroll', sync, { capture: true }) + } }, []) /** diff --git a/stash-web/src/components/common/BackToTop.tsx b/stash-web/src/components/common/BackToTop.tsx index ad66211..68056ff 100644 --- a/stash-web/src/components/common/BackToTop.tsx +++ b/stash-web/src/components/common/BackToTop.tsx @@ -9,5 +9,5 @@ type BackToTopProps = { } export function BackToTop({ visible }: BackToTopProps) { - return + return } diff --git a/stash-web/src/components/content/AppCard.tsx b/stash-web/src/components/content/AppCard.tsx index 6dafb0c..794c52e 100644 --- a/stash-web/src/components/content/AppCard.tsx +++ b/stash-web/src/components/content/AppCard.tsx @@ -24,8 +24,9 @@ export function AppCard({ item, onOpen }: AppCardProps) { }} > onOpen(item.id)} /> {onOpen === undefined ? ( diff --git a/stash-web/src/components/content/SectionCard.tsx b/stash-web/src/components/content/SectionCard.tsx index 4f464f6..81ce2c4 100644 --- a/stash-web/src/components/content/SectionCard.tsx +++ b/stash-web/src/components/content/SectionCard.tsx @@ -21,7 +21,7 @@ export function SectionCard({ title, count, barColor, onMore, children }: Sectio