feat: 站点媒体库与移动端底部导航,服务测试补强
- 新增媒体库:media_library/media_thumbs 服务(WebP 缩略图)、管理端 media 页面 - 移动端底部导航 MobileTabBar 替换 MobilePostBar - 旧数据导入增强与测试、路由与登录会话/板块侧边栏测试补强 - site-doc 组件精简(移除 Breadcrumb),文档新增迁移公告说明
This commit is contained in:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user