Revert "style(admin): 统一标题层级与页面排版"

This reverts commit b1f7589538.
This commit is contained in:
2026-11-02 19:54:36 +08:00
parent b1f7589538
commit bbfbc77b30
2 changed files with 54 additions and 163 deletions
+1 -62
View File
@@ -787,67 +787,7 @@
} }
.admin-form { .admin-form {
margin-top: 0; margin-top: var(--su-space-5);
}
.admin-form-narrow {
max-width: 820px;
}
/* 每个后台页面统一的标题区 */
.admin-panel-head {
display: flex;
align-items: flex-start;
justify-content: space-between;
gap: var(--su-space-5);
padding-bottom: var(--su-space-4);
border-bottom: 1px solid var(--su-border);
margin-bottom: var(--su-space-2);
}
.admin-panel-heading {
min-width: 0;
}
.admin-panel-title {
margin: 0;
color: var(--su-text-main);
font-size: 20px;
font-weight: 700;
line-height: 1.3;
letter-spacing: -0.01em;
}
.admin-panel-desc {
max-width: 760px;
margin: var(--su-space-2) 0 0;
color: var(--su-text-muted);
font-size: var(--su-font-size-sm);
line-height: 1.65;
}
.admin-panel-actions {
display: flex;
flex: none;
flex-wrap: wrap;
align-items: center;
justify-content: flex-end;
gap: var(--su-space-2);
}
/* 表单标签统一加粗,避免组件默认字重在不同字体下发虚 */
.admin-panel label {
font-weight: 600;
}
.admin-inline-actions {
display: flex;
gap: var(--su-space-2);
}
.admin-form-divider {
margin: var(--su-space-1) 0;
border-top: 1px dashed var(--su-border-strong);
} }
.admin-row { .admin-row {
@@ -956,7 +896,6 @@
} }
.admin-actions { .admin-actions {
max-width: 820px;
margin-top: var(--su-space-6); margin-top: var(--su-space-6);
} }
+53 -101
View File
@@ -30,7 +30,7 @@ import {
type IconName, type IconName,
type MenuItem, type MenuItem,
} from '@stash/ui' } from '@stash/ui'
import { useEffect, useMemo, useRef, useState, type ReactNode } from 'react' import { useEffect, useMemo, useRef, useState } from 'react'
import { changePassword, fetchSession, logout, type SessionState } from '../../auth' import { changePassword, fetchSession, logout, type SessionState } from '../../auth'
import { LoginDialog } from '../auth/LoginDialog' import { LoginDialog } from '../auth/LoginDialog'
import { GroupMark as GroupGlyph } from '../common/GroupMark' import { GroupMark as GroupGlyph } from '../common/GroupMark'
@@ -127,27 +127,6 @@ function flattenCardsGroups(groups: GroupNode[]) {
return flattenGroups(groups) return flattenGroups(groups)
} }
/** 后台每个页面统一的标题区:加粗标题 + 说明 + 右侧操作 */
function PanelHeader({
title,
description,
children,
}: {
title: string
description?: string
children?: ReactNode
}) {
return (
<header className="admin-panel-head">
<div className="admin-panel-heading">
<h2 className="admin-panel-title">{title}</h2>
{description !== undefined && <p className="admin-panel-desc">{description}</p>}
</div>
{children !== undefined && <div className="admin-panel-actions">{children}</div>}
</header>
)
}
export function AdminNext() { export function AdminNext() {
const [session, setSession] = useState<SessionState | null>(null) const [session, setSession] = useState<SessionState | null>(null)
const [loginOpen, setLoginOpen] = useState(false) const [loginOpen, setLoginOpen] = useState(false)
@@ -313,9 +292,9 @@ export function AdminNext() {
<main className="admin-main"> <main className="admin-main">
<Card padding="lg"> <Card padding="lg">
<Space direction="column" gap="sm" align="stretch"> <Space direction="column" gap="sm" align="stretch">
<Title level={2}>后台管理</Title> <Title level={2}>站点设置</Title>
<Text size="sm" tone="muted"> <Text size="sm" tone="muted">
管理内容、首页展示与站点设置。 分组是唯一容器;侧边栏和内容卡片都只是勾选分组来组合展示。
</Text> </Text>
</Space> </Space>
@@ -353,10 +332,7 @@ export function AdminNext() {
{tab === 'home-sidebar' && ( {tab === 'home-sidebar' && (
<section className="admin-home-section"> <section className="admin-home-section">
<PanelHeader <Title level={4}>侧边栏</Title>
title="侧边栏"
description="控制资料卡、本地服务与分组导航是否显示;分组本身的显隐由「分组管理」决定。"
/>
<SidebarPanel <SidebarPanel
value={draft.sidebar} value={draft.sidebar}
saving={saving} saving={saving}
@@ -376,10 +352,11 @@ export function AdminNext() {
{tab === 'home-cards' && ( {tab === 'home-cards' && (
<section className="admin-home-section"> <section className="admin-home-section">
<PanelHeader <Title level={4}>内容卡片</Title>
title="内容卡片" <Text size="sm" tone="muted">
description="卡片是首页上的一个区块。勾选它包含的分组,并调整分组顺序与预览条数;停用的分组不会出现在卡片里。" 说明:卡片是首页上的一个区块;在这里勾选它包含哪些分组,并调整这些分组的先后顺序与预览条数。
/> 分组是否启用仍由「分组管理」决定,停用的分组不会出现在卡片里。
</Text>
<CardsPanel <CardsPanel
groups={groups} groups={groups}
cards={cards} cards={cards}
@@ -594,17 +571,18 @@ function GroupsPanel({
return ( return (
<Space direction="column" gap="md" align="stretch" className="admin-form"> <Space direction="column" gap="md" align="stretch" className="admin-form">
<PanelHeader <Text size="sm" tone="muted">
title="分组管理" 说明:分组用于控制前台侧边栏与卡片;可多层嵌套,根分组决定格式。内容(条目)只挂在分组上。
description="分组用于控制前台侧边栏与内容卡片,可多层嵌套;内容(条目)只挂在分组上。" </Text>
>
<div className="group-toolbar">
<Button <Button
icon={<Icon name="add_line" />} icon={<Icon name="add_line" />}
onClick={() => setDialog({ mode: 'root' })} onClick={() => setDialog({ mode: 'root' })}
> >
新建根分组 新建根分组
</Button> </Button>
</PanelHeader> </div>
<Table <Table
size="sm" size="sm"
@@ -612,7 +590,7 @@ function GroupsPanel({
columns={[ columns={[
{ key: 'name', title: '分组名称' }, { key: 'name', title: '分组名称' },
{ key: 'sort', title: '排序权重', width: 110 }, { key: 'sort', title: '排序权重', width: 110 },
{ key: 'count', title: '关联内容数', width: 120 }, { key: 'count', title: '关联网页数', width: 120 },
{ key: 'status', title: '状态', width: 90 }, { key: 'status', title: '状态', width: 90 },
{ key: 'actions', title: '操作', width: 260, align: 'right' }, { key: 'actions', title: '操作', width: 260, align: 'right' },
]} ]}
@@ -1004,30 +982,29 @@ function ContentPanel({ groups, onReload }: { groups: GroupNode[]; onReload: ()
return ( return (
<Space direction="column" gap="md" align="stretch" className="admin-form"> <Space direction="column" gap="md" align="stretch" className="admin-form">
<PanelHeader <Text size="sm" tone="muted">
title="数据管理" 说明:数据只属于一个分组;选中主分组时会连同其所有子分组的数据一起列出。
description="每条数据只属于一个分组;选中主分组时会连同其所有子分组的数据一起列出。" </Text>
>
<div className="entry-toolbar"> <div className="entry-toolbar">
<div className="entry-toolbar-select"> <div className="entry-toolbar-select">
<Select <Select
options={options.map((option) => ({ options={options.map((option) => ({
value: option.key, value: option.key,
label: option.title, label: option.title,
}))} }))}
value={group?.key ?? ''} value={group?.key ?? ''}
onChange={setGroupKey} onChange={setGroupKey}
/> />
</div>
<Button
icon={<Icon name="add_line" />}
disabled={group === undefined}
onClick={() => setDialog({ key: null, groupKey })}
>
新建数据
</Button>
</div> </div>
</PanelHeader> <Button
icon={<Icon name="add_line" />}
disabled={group === undefined}
onClick={() => setDialog({ key: null, groupKey })}
>
新建数据
</Button>
</div>
<Text size="sm" tone="muted"> <Text size="sm" tone="muted">
{group?.title ?? ''} 下共 {rows.length} 条(含子分组) {group?.title ?? ''} 下共 {rows.length} 条(含子分组)
@@ -1356,7 +1333,11 @@ function SidebarPanel({
saving: boolean saving: boolean
}) { }) {
return ( return (
<Space direction="column" gap="md" align="stretch" className="admin-form admin-form-narrow"> <Space direction="column" gap="md" align="stretch">
<Text size="sm" tone="muted">
说明:分组在侧边栏的显隐只由「分组管理 → 状态」决定;这里只管三块侧栏卡片。
</Text>
<ToggleRow <ToggleRow
label="本地管理员" label="本地管理员"
checked={value.show_profile !== false} checked={value.show_profile !== false}
@@ -1458,7 +1439,7 @@ function CardsPanel({
<> <>
<div className="cards-manager"> <div className="cards-manager">
<aside className="cards-side"> <aside className="cards-side">
<Text size="sm" strong> <Text size="sm" tone="muted">
卡片 卡片
</Text> </Text>
<div className="cards-side-new"> <div className="cards-side-new">
@@ -1807,11 +1788,7 @@ function HeaderPanel({
const [tab, setTab] = useState<'site' | 'actions' | 'ticker'>('site') const [tab, setTab] = useState<'site' | 'actions' | 'ticker'>('site')
return ( return (
<Space direction="column" gap="lg" align="stretch" className="admin-form admin-form-narrow"> <Space direction="column" gap="lg" align="stretch" className="admin-form">
<PanelHeader
title="页头"
description="站点标题、Logo、操作图标与滚动信息。修改后点右下角「保存」生效。"
/>
<Tabs <Tabs
className="admin-tabs" className="admin-tabs"
items={[ items={[
@@ -2066,11 +2043,7 @@ function ProfilePanel({
}) { }) {
const update = (patch: Partial<ProfileSettings>) => onChange({ ...value, ...patch }) const update = (patch: Partial<ProfileSettings>) => onChange({ ...value, ...patch })
return ( return (
<Space direction="column" gap="lg" align="stretch" className="admin-form admin-form-narrow"> <Space direction="column" gap="lg" align="stretch" className="admin-form">
<PanelHeader
title="资料管理"
description="这些内容会显示在首页左侧的资料卡上。修改后点右下角「保存」生效。"
/>
<FormField label="头像地址" htmlFor="profile-avatar"> <FormField label="头像地址" htmlFor="profile-avatar">
<Input <Input
id="profile-avatar" id="profile-avatar"
@@ -2132,15 +2105,7 @@ function SystemPanel() {
} }
return ( return (
<Space direction="column" gap="lg" align="stretch" className="admin-form admin-form-narrow"> <Space direction="column" gap="lg" align="stretch" className="admin-form">
<PanelHeader
title="系统管理"
description="账户安全与数据备份。"
/>
<Text size="sm" strong>
修改密码
</Text>
<FormField label="当前密码" htmlFor="current-password"> <FormField label="当前密码" htmlFor="current-password">
<PasswordInput <PasswordInput
id="current-password" id="current-password"
@@ -2160,25 +2125,12 @@ function SystemPanel() {
{message.text} {message.text}
</Notice> </Notice>
)} )}
<div className="admin-inline-actions"> <Button variant="secondary" loading={busy} icon={<Icon name="key_2_line" />} onClick={change}>
<Button variant="secondary" loading={busy} icon={<Icon name="key_2_line" />} onClick={change}> 修改密码
修改密码 </Button>
</Button> <Button icon={<Icon name="download_line" />} onClick={() => window.location.assign('/api/backup')}>
</div> 下载备份
</Button>
<div className="admin-form-divider" />
<Text size="sm" strong>
数据备份
</Text>
<Text size="sm" tone="muted">
下载当前数据库快照(VACUUM INTO),不会中断服务。
</Text>
<div className="admin-inline-actions">
<Button icon={<Icon name="download_line" />} onClick={() => window.location.assign('/api/backup')}>
下载备份
</Button>
</div>
</Space> </Space>
) )
} }