From 1eb213e21561604d2c1cacda6e882222da93f86b Mon Sep 17 00:00:00 2001 From: techotaku39 Date: Sun, 24 May 2026 00:05:47 +0800 Subject: [PATCH] =?UTF-8?q?feat(extension):=20=E4=BE=A7=E8=BE=B9=E6=A0=8F?= =?UTF-8?q?=E4=B8=8E=20popup=20=E7=94=A8=E8=A7=86=E9=A2=91=E6=A0=87?= =?UTF-8?q?=E9=A2=98=E6=9B=BF=E4=BB=A3=E9=93=BE=E6=8E=A5=E6=98=BE=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 在任务未完成的早期阶段(PENDING/DOWNLOADING 等),侧边栏和 popup 只能回退到 videoUrl,用户看到的是一长串链接,难以辨认。 改动: - TaskRecord 新增 title 字段,用于存储浏览器标签页标题 - popup 创建任务时保存 tab.title - background startTask 接收可选 title,右键菜单和悬浮按钮均传入 - 显示优先级:result.audio_meta.title > title > videoUrl - 所有平台(Bilibili / YouTube / Douyin / Kuaishou)均受益 测试: - pnpm typecheck 通过 - pnpm build 通过 - 在 B 站、YouTube 视频页提交任务,侧边栏和 popup 均显示标题而非链接 --- BillNote_extension/src/background/main.ts | 9 +++++---- BillNote_extension/src/contentScripts/views/App.vue | 1 + BillNote_extension/src/logic/types.ts | 2 ++ BillNote_extension/src/popup/Popup.vue | 11 ++++++++--- BillNote_extension/src/sidepanel/Sidepanel.vue | 12 ++++++++---- 5 files changed, 24 insertions(+), 11 deletions(-) diff --git a/BillNote_extension/src/background/main.ts b/BillNote_extension/src/background/main.ts index 9b6ca5f..7883e31 100644 --- a/BillNote_extension/src/background/main.ts +++ b/BillNote_extension/src/background/main.ts @@ -56,7 +56,7 @@ async function upsertTask(record: TaskRecord) { // ---------- 启动任务 ---------- -async function startTask(url: string): Promise<{ ok: boolean, taskId?: string, error?: string }> { +async function startTask(url: string, title?: string): Promise<{ ok: boolean, taskId?: string, error?: string }> { const platform = detectPlatform(url) if (!platform) return { ok: false, error: '当前链接不是支持的视频平台' } @@ -107,6 +107,7 @@ async function startTask(url: string): Promise<{ ok: boolean, taskId?: string, e message: '已提交', createdAt: Date.now(), updatedAt: Date.now(), + title, }) return { ok: true, taskId: body.data.task_id } } @@ -129,8 +130,8 @@ async function openSidePanelInTab(tabId?: number) { // ---------- 消息桥 ---------- -onMessage<{ url: string }, 'bilinote-start'>('bilinote-start', async ({ data, sender }) => { - const result = await startTask(data.url) +onMessage<{ url: string; title?: string }, 'bilinote-start'>('bilinote-start', async ({ data, sender }) => { + const result = await startTask(data.url, data.title) // 成功就把侧边栏拉起来给用户看进度 if (result.ok) await openSidePanelInTab(sender?.tabId) @@ -168,7 +169,7 @@ browser.contextMenus?.onClicked.addListener(async (info, tab) => { const url = info.linkUrl || tab?.url if (!url) return - const result = await startTask(url) + const result = await startTask(url, tab?.title) if (result.ok) await openSidePanelInTab(tab?.id) else diff --git a/BillNote_extension/src/contentScripts/views/App.vue b/BillNote_extension/src/contentScripts/views/App.vue index adbd351..7fcce7a 100644 --- a/BillNote_extension/src/contentScripts/views/App.vue +++ b/BillNote_extension/src/contentScripts/views/App.vue @@ -19,6 +19,7 @@ async function trigger() { const res = await sendMessage('bilinote-start', { url: window.location.href, platform, + title: document.title, }, 'background') const ok = res && (res as any).ok toast.value = ok diff --git a/BillNote_extension/src/logic/types.ts b/BillNote_extension/src/logic/types.ts index 96f18ca..b729ae8 100644 --- a/BillNote_extension/src/logic/types.ts +++ b/BillNote_extension/src/logic/types.ts @@ -79,6 +79,8 @@ export interface TaskRecord { createdAt: number updatedAt: number result?: NoteResult + // 从浏览器 tab.title 抓取,任务完成前用来替代 videoUrl 显示 + title?: string } // 与 backend/app/gpt/prompt_builder.py note_styles 一一对齐 diff --git a/BillNote_extension/src/popup/Popup.vue b/BillNote_extension/src/popup/Popup.vue index 696b93d..83494b2 100644 --- a/BillNote_extension/src/popup/Popup.vue +++ b/BillNote_extension/src/popup/Popup.vue @@ -43,6 +43,7 @@ async function poll(taskId: string) { createdAt: activeTask.value?.createdAt ?? Date.now(), updatedAt: Date.now(), result: res.result ?? activeTask.value?.result, + title: activeTask.value?.title, }) if (res.status !== 'SUCCESS' && res.status !== 'FAILED') pollTimer = setTimeout(() => poll(taskId), 3000) @@ -94,6 +95,7 @@ async function start() { message: '已提交', createdAt: Date.now(), updatedAt: Date.now(), + title: tabTitle.value || undefined, }) poll(task_id) // 提交后顺手把侧边栏拉起来,免得用户来回切窗口 @@ -142,7 +144,10 @@ function selectTask(id: string) { } const activeCover = computed(() => activeTask.value?.result?.audio_meta?.cover_url as string | undefined) -const activeTitle = computed(() => (activeTask.value?.result?.audio_meta?.title as string | undefined) || tabTitle.value) +const activeTitle = computed(() => + (activeTask.value?.result?.audio_meta?.title as string | undefined) + || activeTask.value?.title + || tabTitle.value) function fmtTime(ts?: number) { if (!ts) @@ -331,8 +336,8 @@ onUnmounted(() => { :class="{ 'bg-blue-50': t.taskId === activeTaskId }" @click="selectTask(t.taskId)" > - - {{ (t.result?.audio_meta as { title?: string } | undefined)?.title || t.videoUrl }} + + {{ (t.result?.audio_meta as { title?: string } | undefined)?.title || t.title || t.videoUrl }} {{ t.status }} diff --git a/BillNote_extension/src/sidepanel/Sidepanel.vue b/BillNote_extension/src/sidepanel/Sidepanel.vue index e2587ac..155625b 100644 --- a/BillNote_extension/src/sidepanel/Sidepanel.vue +++ b/BillNote_extension/src/sidepanel/Sidepanel.vue @@ -41,6 +41,7 @@ async function poll(taskId: string) { message: res.message, result: res.result ?? cur.result, updatedAt: Date.now(), + title: cur.title, }) } if (res.status !== 'SUCCESS' && res.status !== 'FAILED') @@ -89,7 +90,10 @@ function downloadMarkdown() { } const activeTitle = computed(() => - (activeTask.value?.result?.audio_meta as { title?: string } | undefined)?.title || activeTask.value?.videoUrl || '') + (activeTask.value?.result?.audio_meta as { title?: string } | undefined)?.title + || activeTask.value?.title + || activeTask.value?.videoUrl + || '') const activeCover = computed(() => (activeTask.value?.result?.audio_meta as { cover_url?: string } | undefined)?.cover_url) @@ -140,8 +144,8 @@ onUnmounted(() => { :class="{ 'bg-white border': t.taskId === activeTaskId }" @click="selectTask(t.taskId)" > - - {{ (t.result?.audio_meta as { title?: string } | undefined)?.title || t.videoUrl }} + + {{ (t.result?.audio_meta as { title?: string } | undefined)?.title || t.title || t.videoUrl }} {{ STAGE_LABELS[t.status] || t.status }} @@ -170,7 +174,7 @@ onUnmounted(() => { class="text-sm font-medium leading-tight line-clamp-1 break-all flex-1 min-w-0 hover:text-blue-600" :href="activeTask.videoUrl" target="_blank" - :title="activeTask.videoUrl" + :title="activeTitle || activeTask.videoUrl" >{{ activeTitle }}