"use client"; import { useEffect, useState } from "react"; import { AdminSettingsActions, AdminSettingsGroup } from "@/components/admin"; import { apiUpdateSiteSettings, type PublicSettings } from "@/lib/api"; import { announcementPath, leaderboardPath, pagePath, postPath, userPath, type UrlStyle } from "@/lib/urlStyle"; import { toast } from "@/lib/toast"; /** 三档风格展示信息:示例 id/slug 固定,方便站长对比形态 */ const STYLE_OPTIONS: { value: UrlStyle; label: string; desc: string }[] = [ { value: "default", label: "标准动态", desc: "框架默认路由,带路径分段" }, { value: "html", label: "静态页 .html", desc: "常见 CMS 伪静态形态" }, { value: "discuz", label: "Discuz 风格", desc: "经典论坛 thread- 形态" }, ]; function samplePaths(style: UrlStyle) { return [ { kind: "帖子", path: postPath(style, 123) }, { kind: "用户", path: userPath(style, 5) }, { kind: "公告", path: announcementPath(style, 1) }, { kind: "自建页", path: pagePath(style, "about") }, { kind: "排行榜", path: leaderboardPath(style) }, ]; } export default function UrlStylePanel({ initial, onSaved, onDirtyChange, }: { initial: PublicSettings; onSaved?: (next: PublicSettings) => void; onDirtyChange?: (dirty: boolean) => void; }) { const [style, setStyle] = useState(initial.url_style); const [savedStyle, setSavedStyle] = useState(initial.url_style); const [saving, setSaving] = useState(false); const [error, setError] = useState(""); const dirty = style !== savedStyle; useEffect(() => { onDirtyChange?.(dirty); }, [dirty, onDirtyChange]); const discard = () => { setStyle(savedStyle); setError(""); }; const save = async () => { if (saving || !dirty) return; setSaving(true); setError(""); try { const res = await apiUpdateSiteSettings({ url_style: style }); setSavedStyle(res.url_style); setStyle(res.url_style); onSaved?.(res); toast("已保存,全站链接风格已切换", "ok"); } catch (e) { const msg = e instanceof Error ? e.message : "保存失败"; setError(msg); toast(msg); } finally { setSaving(false); } }; return ( void save()} onDiscard={discard} /> } >
{STYLE_OPTIONS.map((opt) => { const on = style === opt.value; return ( ); })}
  • 保存后全站前台链接立即按新风格生成;旧风格链接自动 301 到新风格,收录与外链不断链。
  • 301 会被浏览器长期缓存,切换前请想清楚;建议长期固定一种风格,不要频繁来回切换。
  • 自建页与排行榜同样参与伪静态;自建页 slug 含中文时自动 URL 编码,地址栏多数浏览器仍显示中文。
); }