feat: 可配置站点 URL 风格

- 新增 urlStyle 工具与测试:postPath/userPath/sitePagePath 统一生成链接
- 管理端新增 UrlStylePanel 设置面板,settings 服务与 handler 适配
- 全站路由链接与 JSON-LD/sitemap 切换为统一 URL 生成
- middleware 与相关组件适配
This commit is contained in:
2026-09-27 04:01:42 +08:00
parent 1d862a0dd3
commit 7a44c1f2cf
64 changed files with 1183 additions and 200 deletions

View File

@@ -56,6 +56,8 @@ import AutolinkText from "@/components/AutolinkText";
import ConfirmDialog from "@/components/ConfirmDialog";
import ContextMenu, { type CtxMenuItem } from "@/components/ContextMenu";
import ChatUserCard, { type ChatUserCardTarget } from "@/components/ChatUserCard";
import { userPath } from "@/lib/urlStyle";
import { useUrlStyle } from "@/components/SiteBrandProvider";
/** 同一房间已读:进行中去重 + 2s 内合并(滚动/新消息/Strict Mode 连打) */
const MARK_READ_GAP_MS = 2_000;
@@ -102,6 +104,7 @@ function RecallNotice({
meId: number;
members: ChatRoomMember[];
}) {
const urlStyle = useUrlStyle();
if (!message.recalled_at) return null;
const by =
message.recalled_by ||
@@ -137,7 +140,7 @@ function RecallNotice({
const nameNode =
uid > 0 ? (
<Link
href={`/u/${uid}`}
href={userPath(urlStyle, uid)}
className="transition-opacity hover:opacity-80"
style={nameStyle}
>
@@ -2020,6 +2023,7 @@ function MembersPanel({
onOpenCard: (m: ChatRoomMember) => void;
showTitle?: boolean;
}) {
const urlStyle = useUrlStyle();
return (
<div>
{showTitle && (
@@ -2072,7 +2076,7 @@ function MembersPanel({
<Avatar name={name} src={m.user.avatar || undefined} size={28} />
</button>
<Link
href={`/u/${m.user.id}`}
href={userPath(urlStyle, m.user.id)}
className="flex-1 min-w-0 truncate text-[13px] hover:text-[var(--accent)] transition-colors"
style={{ color: "var(--ink)" }}
>