From 8888afd4f54e2f8b72cb109b9d299cf31ec0fb3d Mon Sep 17 00:00:00 2001 From: xiyidaiwa Date: Tue, 11 Aug 2026 00:20:19 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20PR=20=E5=AE=A1=E6=9F=A5=E7=9C=9F?= =?UTF-8?q?=E5=AE=9E=E7=BC=BA=E9=99=B7=E4=BF=AE=E5=A4=8D=EF=BC=88=E5=9B=BE?= =?UTF-8?q?=E6=A0=87=E9=94=99=E4=BD=8D/=E5=AE=9A=E6=97=B6=E5=99=A8?= =?UTF-8?q?=E6=B8=85=E7=90=86/=E5=B9=B6=E5=8F=91/=E7=BB=9F=E8=AE=A1?= =?UTF-8?q?=E5=90=8C=E6=AD=A5=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - AppDetailModal: iconPath 改用 viewingOrigin 动态计算,修复合并源切换时图标与数据错位 - App.vue: onUnmounted 清理 saveBoundsTimer 防抖定时器,避免组件销毁后悬空 IPC 调用 - App.vue: loadHomeListEntries 串行 for-of 改 Promise.all 并发拉取,缩短首页入口加载 - InstalledAppsModal: 顶部统计徽章基于搜索过滤结果实时计算,修复搜索时数字不同步 (审查误报项已核实未改: fetchAppFromStore 已有 encodeURIComponent + AbortSignal) --- src/App.vue | 26 +++++++++++++++----------- src/components/AppDetailModal.vue | 4 +++- src/components/InstalledAppsModal.vue | 15 +++++++++++++-- 3 files changed, 31 insertions(+), 14 deletions(-) diff --git a/src/App.vue b/src/App.vue index 771da690..6b3da917 100644 --- a/src/App.vue +++ b/src/App.vue @@ -1467,13 +1467,15 @@ const loadHomeListEntries = async () => { { name: string; urls: { spark?: string; apm?: string } } >(); - for (const mode of modes) { - const finalArch = mode === "spark" ? `${arch}-store` : `${arch}-apm`; - const base = `${APM_STORE_BASE_URL}/${finalArch}/home`; - - try { - const res = await fetch(`${base}/homelist.json`); - if (res.ok) { + // 并发拉取各来源的 homelist.json(spark/apm),缩短首页入口加载耗时; + // 各来源独立解析后合并到局部 byName,不逐个触发响应式更新。 + await Promise.all( + modes.map(async (mode) => { + const finalArch = mode === "spark" ? `${arch}-store` : `${arch}-apm`; + const base = `${APM_STORE_BASE_URL}/${finalArch}/home`; + try { + const res = await fetch(`${base}/homelist.json`); + if (!res.ok) return; const lists = await res.json(); lists.forEach( (item: { name?: string; type?: string; jsonUrl?: string }) => { @@ -1494,11 +1496,11 @@ const loadHomeListEntries = async () => { } }, ); + } catch (e) { + console.warn(`Failed to load ${mode} homelist.json`, e); } - } catch (e) { - console.warn(`Failed to load ${mode} homelist.json`, e); - } - } + }), + ); const entries: SidebarEntry[] = []; const urlsMap: Record = {}; @@ -3486,6 +3488,8 @@ onMounted(async () => { onUnmounted(() => { rootAbortController.abort(); updateCenterStore.unbind(); + // 清理窗口尺寸防抖定时器,防止组件销毁后仍触发 IPC 保存调用 + if (saveBoundsTimer) clearTimeout(saveBoundsTimer); // 停止仍挂起的"等待 loading 完成后执行一次"的 watcher,避免泄漏 for (const stop of pendingWatchers.splice(0)) stop(); // 移除 window / document 监听 diff --git a/src/components/AppDetailModal.vue b/src/components/AppDetailModal.vue index 0c457b4a..5a011c21 100644 --- a/src/components/AppDetailModal.vue +++ b/src/components/AppDetailModal.vue @@ -783,8 +783,10 @@ const installBtnText = computed(() => { const iconPath = computed(() => { if (!displayApp.value) return ""; const arch = window.apm_store.arch || "amd64"; + // 切换来源标签时(viewingOrigin)需动态重算架构路径,确保图标/资源跟随当前查看来源, + // 而非固定使用合并应用原始 origin,避免切换源时图标与数据错位。 const finalArch = - displayApp.value.origin === "spark" ? `${arch}-store` : `${arch}-apm`; + viewingOrigin.value === "spark" ? `${arch}-store` : `${arch}-apm`; return `${APM_STORE_BASE_URL}/${finalArch}/${displayApp.value.category}/${displayApp.value.pkgname}/icon.png`; }); diff --git a/src/components/InstalledAppsModal.vue b/src/components/InstalledAppsModal.vue index e16ca2eb..93e62559 100644 --- a/src/components/InstalledAppsModal.vue +++ b/src/components/InstalledAppsModal.vue @@ -450,11 +450,22 @@ const hasOrigin = (app: App, origin: "spark" | "apm"): boolean => app.origins?.includes(origin) ?? app.origin === origin; // APM / Spark 分别统计实际安装的包数量(同一 pkgname 同时装两种来源时各计一次) +// 搜索过滤后的全量(不叠加来源筛选),用于顶部统计徽章实时同步搜索结果, +// 避免搜索时列表缩减而徽章数字仍显示全量造成误导。 +const searchFilteredApps = computed(() => { + const q = searchQuery.value.trim().toLowerCase(); + if (!q) return props.apps; + return props.apps.filter( + (a) => + a.name.toLowerCase().includes(q) || a.pkgname.toLowerCase().includes(q), + ); +}); + const apmCount = computed( - () => props.apps.filter((a) => hasOrigin(a, "apm")).length, + () => searchFilteredApps.value.filter((a) => hasOrigin(a, "apm")).length, ); const sparkCount = computed( - () => props.apps.filter((a) => hasOrigin(a, "spark")).length, + () => searchFilteredApps.value.filter((a) => hasOrigin(a, "spark")).length, ); // 总数 = APM 包数 + Spark 包数(不同来源视为不同包,单独计数) const totalCount = computed(() => apmCount.value + sparkCount.value);