From 84fc148a39f25266ee7c4a5246f1a94b42d4dec5 Mon Sep 17 00:00:00 2001 From: CNWei Date: Sun, 1 Nov 2026 16:26:57 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=89=8D=E5=8F=B0=E9=A1=B5=E5=A4=B4?= =?UTF-8?q?=E5=8A=A0=E6=98=8E=E6=9A=97=E5=88=87=E6=8D=A2=EF=BC=8C=E5=88=B7?= =?UTF-8?q?=E6=96=B0=E5=9B=BE=E6=A0=87=E6=8D=A2=E6=88=90=E9=97=AA=E7=94=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - settings.site.actions 新增 theme(默认开),后台「操作工具」可关 - 前台页头:月亮/太阳按钮,点击写回 site.theme,前后台同步; 未登录时不显示(设置接口需要会话) - 刷新图标 refresh_3_line -> lightning_line,刷新期间仍旋转 --- src/db/settings.rs | 4 +++ stash-web/src/AppNext.tsx | 27 ++++++++++++++++++- stash-web/src/components/admin/AdminNext.tsx | 10 +++++++ .../src/components/header/SiteHeader.tsx | 14 +++++++++- stash-web/src/settings.ts | 4 ++- 5 files changed, 56 insertions(+), 3 deletions(-) diff --git a/src/db/settings.rs b/src/db/settings.rs index c7d21cb..3f93038 100644 --- a/src/db/settings.rs +++ b/src/db/settings.rs @@ -188,6 +188,9 @@ impl Default for BrandSettings { #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] #[serde(default)] pub struct ActionSettings { + /// 明暗切换图标 + #[serde(default = "default_true")] + pub theme: bool, /// 刷新图标(重扫本地项目并重拉内容库) pub refresh: bool, /// 站点设置图标(仅登录后出现) @@ -199,6 +202,7 @@ pub struct ActionSettings { impl Default for ActionSettings { fn default() -> Self { Self { + theme: true, refresh: true, settings: true, session: true, diff --git a/stash-web/src/AppNext.tsx b/stash-web/src/AppNext.tsx index 0d11853..2d5e95e 100644 --- a/stash-web/src/AppNext.tsx +++ b/stash-web/src/AppNext.tsx @@ -6,6 +6,7 @@ import { SearchField, Space, Toaster, + toast, type MenuItem, } from '@stash/ui' import { useEffect, useMemo, useRef, useState } from 'react' @@ -26,6 +27,7 @@ import { useProjects } from './useProjects' import { fetchSession, logout, type SessionState } from './auth' import { fetchSettings, + saveSettings, type SettingsDocument, type SiteSettings, } from './settings' @@ -287,7 +289,7 @@ export default function AppNext() { favicon: '', theme: 'auto', brand: { name: 'STASH', mark: 'S', logo: '' }, - actions: { refresh: true, settings: true, session: true }, + actions: { theme: true, refresh: true, settings: true, session: true }, }, } @@ -298,6 +300,27 @@ export default function AppNext() { document.documentElement.dataset.scheme = site.site.theme }, [site.site.theme]) + /** 当前实际是深色吗(auto 时按系统偏好算) */ + const isDark = + site.site.theme === 'dark' || + (site.site.theme === 'auto' && + window.matchMedia('(prefers-color-scheme: dark)').matches) + + /** 页头的明暗切换:写回站点设置,前后台一起变;只有登录后才会显示 */ + const toggleTheme = async () => { + if (settings === null) return + const next = isDark ? 'light' : 'dark' + const result = await saveSettings(settings.version, { + ...settings.settings, + site: { ...settings.settings.site, theme: next }, + }) + if (result.ok) { + setSettings(result.document) + return + } + toast.error(result.error) + } + // 站点级设置:浏览器标签标题与 favicon(空值回落到内置) useEffect(() => { const title = site.site.title.trim() @@ -648,6 +671,8 @@ export default function AppNext() { authenticated={session?.authenticated === true} username={session?.username ?? undefined} refreshing={refreshing} + dark={isDark} + onToggleTheme={() => void toggleTheme()} onRefresh={() => { refresh() load() diff --git a/stash-web/src/components/admin/AdminNext.tsx b/stash-web/src/components/admin/AdminNext.tsx index 69ea500..8699f15 100644 --- a/stash-web/src/components/admin/AdminNext.tsx +++ b/stash-web/src/components/admin/AdminNext.tsx @@ -1935,6 +1935,16 @@ function HeaderPanel({ 操作工具 +
+ 明暗切换 + + onChangeSite({ ...site, actions: { ...site.actions, theme: next } }) + } + label="页头显示明暗切换按钮" + /> +
刷新 void + onToggleTheme: () => void onLogin: () => void onLogout: () => void onSettings: () => void @@ -52,7 +55,9 @@ export function SiteHeader({ authenticated, username, refreshing = false, + dark = false, onRefresh, + onToggleTheme, onLogin, onLogout, onSettings, @@ -84,10 +89,17 @@ export function SiteHeader({ )}
+ {site.actions.theme && ( + } + onClick={onToggleTheme} + /> + )} {site.actions.refresh && ( } + icon={} spinning={refreshing} onClick={onRefresh} /> diff --git a/stash-web/src/settings.ts b/stash-web/src/settings.ts index db51618..5924e03 100644 --- a/stash-web/src/settings.ts +++ b/stash-web/src/settings.ts @@ -82,6 +82,8 @@ export type SiteMetaSettings = { logo: string } actions: { + /** 明暗切换 */ + theme: boolean /** 刷新图标(重扫本地项目并重拉内容库) */ refresh: boolean /** 站点设置图标 */ @@ -143,7 +145,7 @@ export function defaultSettings(): SiteSettings { favicon: '', theme: 'auto', brand: { name: 'STASH', mark: 'S', logo: '' }, - actions: { refresh: true, settings: true, session: true }, + actions: { theme: true, refresh: true, settings: true, session: true }, }, } }