后台设置和内容编辑改成可导航布局;部署用访客 origin 生成 Canonical,避免落到容器地址。 Co-authored-by: Cursor <cursoragent@cursor.com>
63 lines
2.4 KiB
TypeScript
63 lines
2.4 KiB
TypeScript
"use client";
|
||
|
||
import Link from "next/link";
|
||
import { useRouter } from "next/navigation";
|
||
import { useRef } from "react";
|
||
import { MessageSquareText, Clock, Sparkles } from "lucide-react";
|
||
import { useAllowComments } from "@/components/CommentsPolicyProvider";
|
||
|
||
export type FeedSort = "latest" | "new" | "recommended";
|
||
|
||
const TAB_KEYS: FeedSort[] = ["latest", "new", "recommended"];
|
||
|
||
// 在指定板块内切换排序时保留 ?board=;默认排序不写入 URL
|
||
function tabHref(key: FeedSort, boardId: number, allowComments: boolean) {
|
||
const params = new URLSearchParams();
|
||
if (boardId > 0) params.set("board", String(boardId));
|
||
const def = allowComments ? "latest" : "new";
|
||
if (key !== def) params.set("sort", key);
|
||
const qs = params.toString();
|
||
return qs ? `/?${qs}` : "/";
|
||
}
|
||
|
||
// 中栏排序分段控件:URL query 驱动、SSR 直出,键盘 ←/→ 可切换
|
||
export default function FeedTabs({ current, boardId = 0 }: { current: FeedSort; boardId?: number }) {
|
||
const router = useRouter();
|
||
const tabRefs = useRef<(HTMLAnchorElement | null)[]>([]);
|
||
const allowComments = useAllowComments();
|
||
const keys = allowComments ? TAB_KEYS : TAB_KEYS.filter((k) => k !== "latest");
|
||
|
||
const handleKeyDown = (e: React.KeyboardEvent, i: number) => {
|
||
if (e.key !== "ArrowRight" && e.key !== "ArrowLeft") return;
|
||
e.preventDefault();
|
||
const next = (i + (e.key === "ArrowRight" ? 1 : keys.length - 1)) % keys.length;
|
||
tabRefs.current[next]?.focus();
|
||
router.push(tabHref(keys[next], boardId, allowComments));
|
||
};
|
||
|
||
return (
|
||
<div className="flex items-center gap-1.5 sm:gap-2" role="tablist" aria-label="帖子排序">
|
||
{keys.map((key, i) => {
|
||
const Icon = key === "latest" ? MessageSquareText : key === "new" ? Clock : Sparkles;
|
||
return (
|
||
<Link
|
||
key={key}
|
||
ref={(el) => {
|
||
tabRefs.current[i] = el;
|
||
}}
|
||
href={tabHref(key, boardId, allowComments)}
|
||
role="tab"
|
||
className="j13-tab inline-flex items-center gap-1"
|
||
aria-selected={current === key}
|
||
tabIndex={current === key ? 0 : -1}
|
||
onKeyDown={(e) => handleKeyDown(e, i)}
|
||
>
|
||
<Icon size={13} className="opacity-80" />
|
||
{key === "latest" ? "新评论" : key === "new" ? "新帖子" : "推荐帖"}
|
||
</Link>
|
||
);
|
||
})}
|
||
</div>
|
||
);
|
||
}
|