mirror of
https://gitee.com/spark-store-project/spark-store
synced 2026-09-20 21:50:11 +08:00
fix: PR 审查真实缺陷修复(图标错位/定时器清理/并发/统计同步)
- AppDetailModal: iconPath 改用 viewingOrigin 动态计算,修复合并源切换时图标与数据错位 - App.vue: onUnmounted 清理 saveBoundsTimer 防抖定时器,避免组件销毁后悬空 IPC 调用 - App.vue: loadHomeListEntries 串行 for-of 改 Promise.all 并发拉取,缩短首页入口加载 - InstalledAppsModal: 顶部统计徽章基于搜索过滤结果实时计算,修复搜索时数字不同步 (审查误报项已核实未改: fetchAppFromStore 已有 encodeURIComponent + AbortSignal)
This commit is contained in:
+9
-5
@@ -1467,13 +1467,15 @@ const loadHomeListEntries = async () => {
|
||||
{ name: string; urls: { spark?: string; apm?: string } }
|
||||
>();
|
||||
|
||||
for (const mode of modes) {
|
||||
// 并发拉取各来源的 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) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}),
|
||||
);
|
||||
|
||||
const entries: SidebarEntry[] = [];
|
||||
const urlsMap: Record<string, { spark?: string; apm?: string }> = {};
|
||||
@@ -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 监听
|
||||
|
||||
@@ -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`;
|
||||
});
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user