From 59dea6f84c80445c7414c20c662ac4b5e2a75897 Mon Sep 17 00:00:00 2001 From: developer Date: Sun, 12 Jul 2026 13:44:12 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20URL=20=E6=A0=87=E9=A2=98=E6=8A=93?= =?UTF-8?q?=E5=8F=96=E6=94=B9=E4=B8=BA=E9=80=9A=E8=BF=87=E5=90=8E=E7=AB=AF?= =?UTF-8?q?=E4=BB=A3=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 从直连 lpt-ai 的 /fetch-title 改为调用后端 /utils/fetch-title - 使用 Map 缓存 + pending 去重,避免重复请求 - 导出 getUrlTitle 单条获取函数,替代 fetchTitle/fetchTitles --- src/utils/fetchTitle.ts | 50 +++++++++++++++++------------------------ 1 file changed, 20 insertions(+), 30 deletions(-) diff --git a/src/utils/fetchTitle.ts b/src/utils/fetchTitle.ts index 85a5b09..607573a 100644 --- a/src/utils/fetchTitle.ts +++ b/src/utils/fetchTitle.ts @@ -1,36 +1,26 @@ /** - * 网页标题抓取工具。 - * 调用 lpt-ai 的 /fetch-title 接口获取 URL 对应的 标签内容。 - * - * 设计要点: - * - 内存缓存避免同页面重复请求 - * - 失败时回退到 URL 本身 - * - 仅在 lpt-ai 运行时可用 + * URL 标题缓存 + 按需抓取,调用后端 /utils/fetch-title 代理 */ -const LPT_AI_URL = "http://localhost:5199"; +import request from "@/utils/request"; -const titleCache: Record<string, string> = {}; +const cache = new Map<string, string>(); +const pending = new Map<string, Promise<string>>(); -export async function fetchTitle(url: string): Promise<string> { - if (titleCache[url]) return titleCache[url]; - try { - const res = await fetch(`${LPT_AI_URL}/fetch-title`, { - method: "POST", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify({ url }), - signal: AbortSignal.timeout(12_000), - }); - if (!res.ok) return url; - const data = await res.json(); - titleCache[url] = data.title || url; - return titleCache[url]; - } catch { - return url; - } -} - -/** 批量获取标题 */ -export async function fetchTitles(urls: string[]): Promise<string[]> { - return Promise.all(urls.map((url) => fetchTitle(url))); +export async function getUrlTitle(url: string): Promise<string> { + if (cache.has(url)) return cache.get(url)!; + if (pending.has(url)) return pending.get(url)!; + + const promise = request + .get("/utils/fetch-title", { url }) + .then((res: any) => { + const title = res?.data?.title || url; + cache.set(url, title); + return title; + }) + .catch(() => url) + .finally(() => pending.delete(url)); + + pending.set(url, promise); + return promise; }