feat: hashtag 列表显示按共现计算的相关 tag
- 新增 /api/hashtag/related:从作品描述实时解析 hashtag,按「同一作品里一起出现」计算相关 tag - 打分取子话题(候选多与目标同现)与上位话题(目标多与热门候选同现)两者较大值, 过滤 cos、二次元等万金油 tag 与平台活动、纯数字 tag - 播放页侧栏的 hashtag 列表顶部显示相关 tag,点击在侧栏内预览(不打断当前播放), 在预览里点作品才切换到该 tag 的列表 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,37 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import type { RelatedHashtagsResult } from "@/lib/hashtag-related.server";
|
||||
|
||||
const cache = new Map<string, RelatedHashtagsResult>();
|
||||
|
||||
/** 取某个 hashtag 的相关 tag(按共现计算);name 为空或 enabled 为 false 时不请求。 */
|
||||
export function useRelatedHashtags(
|
||||
name: string | null,
|
||||
enabled: boolean,
|
||||
): RelatedHashtagsResult | null {
|
||||
const key = name?.toLowerCase() ?? "";
|
||||
const [result, setResult] = useState<RelatedHashtagsResult | null>(
|
||||
() => cache.get(key) ?? null,
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (!key || !enabled) return;
|
||||
const cached = cache.get(key);
|
||||
setResult(cached ?? null);
|
||||
if (cached) return;
|
||||
|
||||
let cancelled = false;
|
||||
fetch(`/api/hashtag/related?name=${encodeURIComponent(key)}`)
|
||||
.then((res) => (res.ok ? res.json() : null))
|
||||
.then((data: RelatedHashtagsResult | null) => {
|
||||
if (!data) return;
|
||||
cache.set(key, data);
|
||||
if (!cancelled) setResult(data);
|
||||
})
|
||||
.catch(() => {});
|
||||
return () => {
|
||||
cancelled = true;
|
||||
};
|
||||
}, [key, enabled]);
|
||||
|
||||
return result?.name === key ? result : null;
|
||||
}
|
||||
Reference in New Issue
Block a user