fix: 排序栏 count 紧跟标签,FeedSortBar 与 SSR 统一为 a 标签
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
import { useMemo, useRef } from 'react';
|
import { useMemo, useRef } from 'react';
|
||||||
import { boardPath, type PermalinkOpts } from '../utils/permalink';
|
import { useParams, useSearchParams } from 'react-router-dom';
|
||||||
|
import { boardPath, parsePermalinkID, type PermalinkOpts } from '../utils/permalink';
|
||||||
import { getCachedForumLimits, useForumLimits } from '../hooks/useForumLimits';
|
import { getCachedForumLimits, useForumLimits } from '../hooks/useForumLimits';
|
||||||
import { Clock, MessageCircle, BadgeCheck, Loader2 } from 'lucide-react';
|
import { Clock, MessageCircle, BadgeCheck, Loader2 } from 'lucide-react';
|
||||||
import { cn } from '@/lib/utils';
|
import { cn } from '@/lib/utils';
|
||||||
@@ -86,14 +87,35 @@ export default function FeedSortBar({
|
|||||||
pendingValue,
|
pendingValue,
|
||||||
}: Props) {
|
}: Props) {
|
||||||
const { limits } = useForumLimits();
|
const { limits } = useForumLimits();
|
||||||
|
const { id: boardRouteId } = useParams();
|
||||||
|
const [params] = useSearchParams();
|
||||||
|
// 与 SSR href / HomePage 一致:从路由与查询串解析板块与筛选
|
||||||
|
const boardId = boardRouteId
|
||||||
|
? (() => {
|
||||||
|
const id = parsePermalinkID(boardRouteId);
|
||||||
|
return Number.isFinite(id) && id > 0 ? id : 0;
|
||||||
|
})()
|
||||||
|
: (Number(params.get('board')) || 0);
|
||||||
|
const keyword = params.get('keyword') || '';
|
||||||
|
const tag = params.get('tag') || '';
|
||||||
|
const author = params.get('author') || '';
|
||||||
|
const titleOnly = params.get('title_only') === '1';
|
||||||
|
|
||||||
const options = useMemo(
|
const options = useMemo(
|
||||||
() => enabledFeedSortTabs(limits.feed_sort_tabs).map(t => ({
|
() => enabledFeedSortTabs(limits.feed_sort_tabs).map(t => ({
|
||||||
key: t.id as FeedSort,
|
key: t.id as FeedSort,
|
||||||
label: t.label,
|
label: t.label,
|
||||||
hint: SORT_META[t.id]?.hint ?? '',
|
hint: SORT_META[t.id]?.hint ?? '',
|
||||||
icon: SORT_META[t.id]?.icon ?? Clock,
|
icon: SORT_META[t.id]?.icon ?? Clock,
|
||||||
|
href: buildHomeUrl(boardId, t.id as FeedSort, {
|
||||||
|
keyword,
|
||||||
|
tag,
|
||||||
|
author,
|
||||||
|
titleOnly,
|
||||||
|
permalink: limits,
|
||||||
|
}),
|
||||||
})),
|
})),
|
||||||
[limits.feed_sort_tabs],
|
[limits, boardId, keyword, tag, author, titleOnly],
|
||||||
);
|
);
|
||||||
|
|
||||||
const listRef = useRef<HTMLDivElement>(null);
|
const listRef = useRef<HTMLDivElement>(null);
|
||||||
@@ -121,25 +143,28 @@ export default function FeedSortBar({
|
|||||||
aria-label="帖子排序"
|
aria-label="帖子排序"
|
||||||
onKeyDown={onKeyDown}
|
onKeyDown={onKeyDown}
|
||||||
>
|
>
|
||||||
{options.map(({ key, label, hint, icon: Icon }, i) => {
|
{options.map(({ key, label, hint, icon: Icon, href }, i) => {
|
||||||
const pending = pendingValue === key;
|
const pending = pendingValue === key;
|
||||||
return (
|
return (
|
||||||
<button
|
<a
|
||||||
key={key}
|
key={key}
|
||||||
type="button"
|
href={href}
|
||||||
role="tab"
|
role="tab"
|
||||||
tabIndex={activeIndex === i ? 0 : -1}
|
tabIndex={activeIndex === i ? 0 : -1}
|
||||||
aria-selected={value === key}
|
aria-selected={value === key}
|
||||||
aria-busy={pending || undefined}
|
aria-busy={pending || undefined}
|
||||||
title={`${label} · ${hint}`}
|
title={`${label} · ${hint}`}
|
||||||
className={cn('feed-sort-tab', value === key && 'active', pending && 'is-pending')}
|
className={cn('feed-sort-tab', value === key && 'active', pending && 'is-pending')}
|
||||||
onClick={() => onChange(key)}
|
onClick={(e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
onChange(key);
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
{pending
|
{pending
|
||||||
? <Loader2 className="feed-sort-tab__spin" aria-hidden />
|
? <Loader2 className="feed-sort-tab__spin" aria-hidden />
|
||||||
: <Icon aria-hidden />}
|
: <Icon aria-hidden />}
|
||||||
<span className="feed-sort-tab__label">{label}</span>
|
<span className="feed-sort-tab__label">{label}</span>
|
||||||
</button>
|
</a>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -2791,12 +2791,12 @@ a.post-row {
|
|||||||
.board-chip.active.board-chip--6 { background: var(--board-6-bg); color: var(--board-6-color); }
|
.board-chip.active.board-chip--6 { background: var(--board-6-bg); color: var(--board-6-color); }
|
||||||
.board-chip.active.board-chip--7 { background: var(--board-7-bg); color: var(--board-7-color); }
|
.board-chip.active.board-chip--7 { background: var(--board-7-bg); color: var(--board-7-color); }
|
||||||
|
|
||||||
/* 帖子排序栏:与左侧栏 active 样式保持一致 */
|
/* 帖子排序栏:与左侧栏 active 样式保持一致;不占满整行,避免「共 N 条」贴中栏右缘 */
|
||||||
.feed-sort-bar {
|
.feed-sort-bar {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 2px;
|
gap: 2px;
|
||||||
flex: 1;
|
flex: 0 1 auto;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
scrollbar-width: none;
|
scrollbar-width: none;
|
||||||
@@ -2819,6 +2819,7 @@ a.post-row {
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
|
text-decoration: none;
|
||||||
transition: background 0.15s, color 0.15s;
|
transition: background 0.15s, color 0.15s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user