diff --git a/HANDOFF.md b/HANDOFF.md index a772e7f..cc2b112 100644 --- a/HANDOFF.md +++ b/HANDOFF.md @@ -113,7 +113,6 @@ stash-ui/src/components/ SearchField / Input / EngineIcon 等 "header": { "enabled": true, "speed": 24, "gap": 26, "items": [...] }, "sidebar": { "show_profile": true, "show_service": false, "show_nav": true }, "background": { "light": "", "dark": "" }, // 空 = 内置背景 - "card": { "opacity": 100, "blur": false }, // 卡片不透明度 40–100 + 毛玻璃 "search": { "default": "internal", "engines": [ @@ -148,7 +147,6 @@ stash-ui/src/components/ SearchField / Input / EngineIcon 等 - 搜索框:默认搜索项、五个外部引擎的名称 / URL / 启停、恢复默认; - 侧边栏:资料卡 / 本地服务 / 分组导航显隐; - 内容卡片:卡片 + 勾选分组 + 预览条数 + 排序; - - 卡片外观:前台所有卡片的不透明度(40–100)与毛玻璃开关; - **资料管理**:头像、名称、角色、简介、位置; - **系统管理**:改密码、下载备份。 diff --git a/README.md b/README.md index 25a88ec..6526f5c 100644 --- a/README.md +++ b/README.md @@ -54,7 +54,7 @@ cargo run -- --root ./sites --host 0.0.0.0 --port 3000 - 登录后点「站点设置」进入 `/admin`,左侧导航 + 右侧内容: - **分组管理**:树形表格,可建根 / 子分组、图标(字符或 iconfont 图标名)、排序权重、启停、删除; - **数据管理**:选分组后列出条目(含子分组),每条可单独设格式,可新建 / 编辑 / 删除; - - **首页管理**(子项):**页头**(站点信息 / 操作工具 / 滚动信息三个页签)、**侧边栏**(三块侧栏卡片显隐)、**内容卡片**(左侧可拖拽排序的卡片列表 + 右侧分组表格:状态、预览条数、顺序、展示)、**卡片外观**(所有卡片的不透明度 40–100 与毛玻璃开关); + - **首页管理**(子项):**页头**(站点信息 / 操作工具 / 滚动信息三个页签)、**侧边栏**(三块侧栏卡片显隐)、**内容卡片**(左侧可拖拽排序的卡片列表 + 右侧分组表格:状态、预览条数、顺序、展示); - **资料管理**与**系统管理**(改密码、下载整库备份); - 分组的「状态」是**唯一可见性来源**:停用的分组在侧栏和卡片里都不再出现,层层往下生效; - 详情页的 `[编辑]` 只在登录后显示;保存后局部刷新,`updated_at` 乐观锁; diff --git a/src/db/settings.rs b/src/db/settings.rs index 9d90a33..b9b942c 100644 --- a/src/db/settings.rs +++ b/src/db/settings.rs @@ -13,8 +13,6 @@ pub const SETTINGS_KEY: &str = "site"; pub const MAX_HEADER_ITEMS: usize = 8; pub const MIN_SPEED: u32 = 8; pub const MAX_SPEED: u32 = 120; -pub const MIN_CARD_OPACITY: u32 = 40; -pub const MAX_CARD_OPACITY: u32 = 100; #[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, Default)] #[serde(rename_all = "snake_case")] @@ -121,25 +119,6 @@ pub struct BackgroundSettings { pub dark: String, } -/// 卡片外观:透明度与毛玻璃。前台所有卡片共用一套(首页 / 分组页 / 详情页 / 侧栏)。 -#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] -#[serde(default)] -pub struct CardSettings { - /// 卡片底色的不透明度(百分比,40–100) - pub opacity: u32, - /// 毛玻璃:背景模糊 + 提饱和度 - pub blur: bool, -} - -impl Default for CardSettings { - fn default() -> Self { - Self { - opacity: 100, - blur: false, - } - } -} - #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Default)] #[serde(default)] pub struct SearchEngineSettings { @@ -309,7 +288,6 @@ pub struct Settings { pub header: HeaderSettings, pub sidebar: SidebarSettings, pub background: BackgroundSettings, - pub card: CardSettings, pub search: SearchSettings, pub profile: ProfileSettings, pub site: SiteMetaSettings, @@ -376,11 +354,6 @@ pub fn validate(settings: &Settings) -> Result<(), StashError> { "暗色背景地址最多 500 个字符".into(), )); } - if !(MIN_CARD_OPACITY..=MAX_CARD_OPACITY).contains(&settings.card.opacity) { - return Err(StashError::InvalidDirectory(format!( - "卡片不透明度需在 {MIN_CARD_OPACITY}–{MAX_CARD_OPACITY} 之间" - ))); - } if settings.search.engines.len() > 10 { return Err(StashError::InvalidDirectory("搜索引擎最多 10 个".into())); } @@ -578,14 +551,6 @@ mod tests { let mut empty = Settings::default(); empty.header.items.clear(); assert!(save(&mut conn, empty, 0).is_err()); - - let mut too_transparent = Settings::default(); - too_transparent.card.opacity = MIN_CARD_OPACITY - 1; - assert!(save(&mut conn, too_transparent, 0).is_err()); - - let mut clear = Settings::default(); - clear.card.opacity = MAX_CARD_OPACITY; - assert!(save(&mut conn, clear, 0).is_ok()); } #[test] diff --git a/stash-web/src/App.css b/stash-web/src/App.css index f0a5943..aff51bf 100644 --- a/stash-web/src/App.css +++ b/stash-web/src/App.css @@ -14,26 +14,6 @@ --su-card-border: var(--su-border-strong); } -/* 卡片外观(后台「卡片外观」可调):底色透明度 + 毛玻璃,前台所有卡片共用一套。 - 变量由 AppNext 按站点设置写到 上;没设置时就是实底、无毛玻璃。 */ -.app .section-card, -.app .profile-card, -.app .service-panel, -.app .nav-card, -.app .group-own-block, -.app .group-child-block, -.app .detail-nav, -.app .item-card, -.app .article-body-card, -.app .related-card { - background-color: color-mix( - in srgb, - var(--su-bg-card) var(--stash-card-alpha, 100%), - transparent - ); - backdrop-filter: var(--stash-card-blur, none); -} - /* 卡片阴影默认会被滚动容器在左右边缘一刀切掉(卡片正好贴着容器边)。 负边距把容器撑宽 16px、再补同样的内边距,内容位置不变,阴影有地方画。 */ #page-scroll { @@ -396,6 +376,16 @@ margin-top: var(--su-space-2); } +/* 分组页的内容直接压在背景图上(没有卡片底):靠文字自己的对比来保证可读, + 次级文字提一档,再加一层同主题的描边,落在图片亮部也不会糊成一片。 */ +.detail-view .group-own-block, +.detail-view .group-child-block, +.detail-hero { + --su-text-sub: var(--su-text-secondary); + --su-text-muted: var(--su-text-sub); + text-shadow: 0 1px 3px color-mix(in srgb, var(--su-bg-page) 70%, transparent); +} + /* 明细页的分组标题:与首页卡片标题同一套「色条 + 标题」 */ .group-title { display: flex; diff --git a/stash-web/src/AppNext.tsx b/stash-web/src/AppNext.tsx index 8e83135..b9e3d42 100644 --- a/stash-web/src/AppNext.tsx +++ b/stash-web/src/AppNext.tsx @@ -333,7 +333,6 @@ export default function AppNext() { show_nav: true, }, background: cachedBackground ?? { light: '', dark: '' }, - card: { opacity: 100, blur: false }, search: { default: 'internal', engines: DEFAULT_SEARCH_ENGINES.map((engine) => ({ ...engine })), @@ -409,13 +408,6 @@ export default function AppNext() { } }, [scheme]) - // 卡片外观:透明度和毛玻璃写在 的 CSS 变量上,前台所有卡片共用一套 - useEffect(() => { - const root = document.documentElement.style - root.setProperty('--stash-card-alpha', `${site.card.opacity}%`) - root.setProperty('--stash-card-blur', site.card.blur ? 'blur(14px) saturate(1.15)' : 'none') - }, [site.card.opacity, site.card.blur]) - /** 页头的明暗切换:只写本机偏好,不需要登录;站点默认值在后台改 */ const toggleTheme = () => { const next: ThemeChoice = isDark ? 'light' : 'dark' @@ -668,9 +660,7 @@ export default function AppNext() { {group.entries.length > 0 ? ( - - {renderEntries(group, group.entries)} - +
{renderEntries(group, group.entries)}
) : group.children.some((child) => groupEntryCount(child) > 0) ? null : ( )} @@ -679,7 +669,7 @@ export default function AppNext() { {group.children .filter((child) => child.enabled !== false) .map((child) => ( - +
)} - +
))} diff --git a/stash-web/src/components/admin/AdminNext.tsx b/stash-web/src/components/admin/AdminNext.tsx index 5d02de7..aa6f4ba 100644 --- a/stash-web/src/components/admin/AdminNext.tsx +++ b/stash-web/src/components/admin/AdminNext.tsx @@ -83,7 +83,6 @@ type TabKey = | 'content' | 'home-sidebar' | 'home-cards' - | 'home-cards-look' | 'home-header' | 'home-background' | 'home-search' @@ -103,7 +102,6 @@ const ADMIN_NAV: MenuItem[] = [ { key: 'home-search', label: '搜索框' }, { key: 'home-sidebar', label: '侧边栏' }, { key: 'home-cards', label: '内容卡片' }, - { key: 'home-cards-look', label: '卡片外观' }, ], }, { key: 'profile', label: '资料管理' }, @@ -392,16 +390,6 @@ export function AdminNext() { /> )} - {tab === 'home-cards-look' && ( -
- 卡片外观 - setDraft({ ...draft, card })} - /> -
- )} - {tab === 'home-background' && (