From 0375669a6e18c6d866a29fcc896a06b54bba76a1 Mon Sep 17 00:00:00 2001 From: CNWei Date: Sun, 1 Nov 2026 20:36:11 +0800 Subject: [PATCH] =?UTF-8?q?feat(admin):=20=E9=A1=B5=E5=A4=B4=E6=8B=86?= =?UTF-8?q?=E6=88=90=E4=B8=89=E4=B8=AA=E5=AD=90=E9=A1=B5=E7=AD=BE=EF=BC=8C?= =?UTF-8?q?=E5=AF=BC=E8=88=AA=E9=A1=BA=E5=BA=8F=E4=B8=8E=E5=91=BD=E5=90=8D?= =?UTF-8?q?=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 首页管理下顺序改为 页头 / 侧边栏 / 内容卡片,默认展开 - 资料 -> 资料管理、系统 -> 系统管理 - 页头面板内用水平页签分为 站点信息 / 操作工具 / 滚动信息 - 滚动信息页列出可用通配符 {count} / {project} / {status} 及含义 --- stash-web/src/App.css | 22 + stash-web/src/components/admin/AdminNext.tsx | 433 ++++++++++--------- 2 files changed, 260 insertions(+), 195 deletions(-) diff --git a/stash-web/src/App.css b/stash-web/src/App.css index f287654..129fcd4 100644 --- a/stash-web/src/App.css +++ b/stash-web/src/App.css @@ -53,6 +53,28 @@ padding: 0 var(--su-space-5); } +/* 通配符说明:两列小表 */ +.ticker-vars { + display: grid; + grid-template-columns: auto minmax(0, 1fr); + gap: var(--su-space-2) var(--su-space-4); + align-items: center; + padding: var(--su-space-3); + border: 1px solid var(--su-border); + border-radius: var(--su-radius-md); + background-color: var(--su-bg-subtle); + font-size: var(--su-font-size-sm); +} + +.ticker-vars code { + padding: 0 var(--su-space-2); + border-radius: var(--su-radius-xs); + background-color: var(--su-bg-card); + color: var(--su-color-primary); + font-family: var(--su-font-mono); + justify-self: start; +} + /* 后台:左侧导航 + 右侧内容 */ .admin-shell { display: grid; diff --git a/stash-web/src/components/admin/AdminNext.tsx b/stash-web/src/components/admin/AdminNext.tsx index 394e72c..71f5a96 100644 --- a/stash-web/src/components/admin/AdminNext.tsx +++ b/stash-web/src/components/admin/AdminNext.tsx @@ -14,6 +14,7 @@ import { Select, Space, Switch, + Tabs, Tag, Text, Textarea, @@ -81,13 +82,13 @@ const ADMIN_NAV: MenuItem[] = [ key: 'home', label: '首页管理', children: [ + { key: 'home-header', label: '页头' }, { key: 'home-sidebar', label: '侧边栏' }, { key: 'home-cards', label: '内容卡片' }, - { key: 'home-header', label: '页头' }, ], }, - { key: 'profile', label: '资料' }, - { key: 'system', label: '系统' }, + { key: 'profile', label: '资料管理' }, + { key: 'system', label: '系统管理' }, ] const FORMAT_OPTIONS = [ @@ -308,6 +309,7 @@ export function AdminNext() { activeKey={tab} onSelect={(key) => setTab(key as TabKey)} itemHeight={40} + defaultOpenKeys={['home']} /> @@ -1900,206 +1902,247 @@ function HeaderPanel({ site: SiteSettings['site'] onChangeSite: (site: SiteSettings['site']) => void }) { + const [tab, setTab] = useState<'site' | 'actions' | 'ticker'>('site') + return ( - - 站点信息 - - - onChangeSite({ ...site, title: event.target.value })} - /> - - - onChangeSite({ ...site, favicon: event.target.value })} - /> - - - - onChangeSite({ ...site, brand: { ...site.brand, logo: event.target.value } }) - } - /> - -
- - - onChangeSite({ ...site, brand: { ...site.brand, name: event.target.value } }) - } - /> - - - - onChangeSite({ ...site, brand: { ...site.brand, mark: event.target.value } }) - } - /> - -
+ {tab === 'site' && ( + + + onChangeSite({ ...site, title: event.target.value })} + /> + + + onChangeSite({ ...site, favicon: event.target.value })} + /> + + + + onChangeSite({ ...site, brand: { ...site.brand, logo: event.target.value } }) + } + /> + +
+ + + onChangeSite({ ...site, brand: { ...site.brand, name: event.target.value } }) + } + /> + + + + onChangeSite({ ...site, brand: { ...site.brand, mark: event.target.value } }) + } + /> + +
+
+ )} - - 滚动信息 - -
- 显示页头滚动信息 - onChange({ ...value, enabled })} - label="显示页头滚动信息" - /> -
- - { - const speed = Number(event.target.value) - if (Number.isFinite(speed)) onChange({ ...value, speed }) - }} - /> - - {value.items.map((item, index) => ( -
- - onChange({ - ...value, - items: value.items.map((current, currentIndex) => - currentIndex === index ? { ...current, text: event.target.value } : current, - ), - }) - } - /> - - onChange({ - ...value, - items: value.items.map((current, currentIndex) => - currentIndex === index ? { ...current, tag: event.target.value } : current, - ), - }) - } - /> - { + const speed = Number(event.target.value) + if (Number.isFinite(speed)) onChange({ ...value, speed }) + }} + /> + + + + 可用通配符 + + + 说明:下面这些占位符写在「信息文本」里,渲染时会替换成实时值;写别的花括号不会替换。 + +
+ {'{count}'} + 本地应用数量 + {'{project}'} + 第一个本地项目的名字(没有项目时显示 —) + {'{status}'} + 实时同步状态:实时同步已连接 / 等待服务连接 +
+ + + 信息条目 + + {value.items.map((item, index) => ( +
+ + onChange({ + ...value, + items: value.items.map((current, currentIndex) => + currentIndex === index ? { ...current, text: event.target.value } : current, + ), + }) + } + /> + + onChange({ + ...value, + items: value.items.map((current, currentIndex) => + currentIndex === index ? { ...current, tag: event.target.value } : current, + ), + }) + } + /> +