feat: 站点媒体库与移动端底部导航,服务测试补强

- 新增媒体库:media_library/media_thumbs 服务(WebP 缩略图)、管理端 media 页面
- 移动端底部导航 MobileTabBar 替换 MobilePostBar
- 旧数据导入增强与测试、路由与登录会话/板块侧边栏测试补强
- site-doc 组件精简(移除 Breadcrumb),文档新增迁移公告说明
This commit is contained in:
2026-09-27 02:35:38 +08:00
parent 734afbc39f
commit 1d862a0dd3
61 changed files with 4757 additions and 1129 deletions

View File

@@ -180,6 +180,16 @@ export default function SidebarAdmin({
}
};
// 放弃未保存修改:回到最近一次保存的布局
const discardChanges = () => {
if (busy) return;
try {
setConfig(JSON.parse(savedJsonRef.current));
} catch {
/* 忽略:快照损坏时保持现状 */
}
};
/* ---------- 自定义工具 ---------- */
const openCreate = () => {
@@ -304,16 +314,41 @@ export default function SidebarAdmin({
</nav>
);
// 页头与浮动保存条共用的未保存提示 + 操作按钮
const dirtyDot = (
<span
className="inline-block w-2 h-2 rounded-full animate-pulse shrink-0"
style={{ background: "var(--gold)" }}
aria-hidden
/>
);
const saveControls = dirty ? (
<div className="flex items-center gap-2">
<span className="meta flex items-center gap-1.5 text-[12px]">
{dirtyDot}
布局有未保存的修改
</span>
<button type="button" className="btn btn-line btn-sm" disabled={busy} onClick={discardChanges}>
撤销修改
</button>
<button type="button" className="btn btn-primary btn-sm" disabled={busy} onClick={() => void saveConfig()}>
{busy ? "保存中…" : "保存布局"}
</button>
</div>
) : undefined;
return (
<AdminSettingsPage>
<AdminPageHeader
icon={PanelLeft}
title="侧栏管理"
description="配置各页面左右侧栏的显示、顺序与位置,管理自定义 HTML 工具"
actions={saveControls}
/>
<AdminSettingsWork nav={leftNav}>
<div className="space-y-5 pb-24">
<>
<div className="space-y-5 pb-4">
{SIDES.map(({ scope, icon, desc, sides }) => {
const sc = config.scopes[scope] ?? {};
const left = sc.left ?? [];
@@ -413,27 +448,34 @@ export default function SidebarAdmin({
</div>
</section>
</div>
</AdminSettingsWork>
{/* 吸底保存栏 */}
{dirty && (
<div
className="fixed bottom-0 left-0 right-0 z-40 flex items-center justify-between gap-3 border-t px-4 py-3 sm:px-6"
style={{
background: "color-mix(in srgb, var(--panel) 92%, transparent)",
backdropFilter: "blur(12px)",
borderColor: "var(--line)",
}}
>
<p className="meta text-[12px]">
<span className="inline-block w-2 h-2 rounded-full mr-1.5" style={{ background: "var(--gold)" }} aria-hidden />
布局有未保存的修改
</p>
<button type="button" className="btn btn-primary" disabled={busy} onClick={() => void saveConfig()}>
{busy ? "保存中…" : "保存布局"}
</button>
</div>
)}
{/* 浮动保存条:吸在内容列底部居中,滚动全程可见,不再贴屏幕角落 */}
{dirty && (
<div className="sticky bottom-4 z-30 flex justify-center pointer-events-none">
<div
className="pointer-events-auto flex items-center gap-3 rounded-full px-4 py-2"
style={{
background: "color-mix(in srgb, var(--panel) 92%, transparent)",
backdropFilter: "blur(12px)",
border: "1px solid var(--line)",
boxShadow: "var(--shadow-lg)",
}}
>
<span className="meta flex items-center gap-1.5 text-[12px]">
{dirtyDot}
布局有未保存的修改
</span>
<button type="button" className="btn btn-line btn-sm" disabled={busy} onClick={discardChanges}>
撤销修改
</button>
<button type="button" className="btn btn-primary btn-sm" disabled={busy} onClick={() => void saveConfig()}>
{busy ? "保存中…" : "保存布局"}
</button>
</div>
</div>
)}
</>
</AdminSettingsWork>
{/* 工具编辑弹层 */}
<Modal