mirror of
https://gitee.com/spark-store-project/spark-store
synced 2026-08-06 10:23:57 +08:00
refactor(sidebar): 优化侧边栏加载逻辑,支持按来源仓库过滤请求
1. 新增SidebarEntry的origins字段标记入口所属仓库 2. 合并多仓库共享的侧边栏入口配置 3. 仅向实际存在的仓库发起分类和应用加载请求,减少无效404请求 4. 并行加载分类数据避免串行等待,调整预加载顺序优化网络资源占用
This commit is contained in:
+63
-39
@@ -2499,13 +2499,20 @@ const loadSidebarConfig = async () => {
|
|||||||
|
|
||||||
for (const entry of entries) {
|
for (const entry of entries) {
|
||||||
if (entry.id && entry.name) {
|
if (entry.id && entry.name) {
|
||||||
if (!entryMap.has(entry.id)) {
|
const existing = entryMap.get(entry.id);
|
||||||
|
if (existing) {
|
||||||
|
// 多仓库共有入口,合并来源
|
||||||
|
if (existing.origins && !existing.origins.includes(mode)) {
|
||||||
|
existing.origins.push(mode);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
entryMap.set(entry.id, {
|
entryMap.set(entry.id, {
|
||||||
id: entry.id,
|
id: entry.id,
|
||||||
name: entry.name,
|
name: entry.name,
|
||||||
icon: entry.icon || "",
|
icon: entry.icon || "",
|
||||||
type: entry.type || "category",
|
type: entry.type || "category",
|
||||||
value: entry.value || entry.id,
|
value: entry.value || entry.id,
|
||||||
|
origins: [mode],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2557,42 +2564,54 @@ const loadTabCategories = async () => {
|
|||||||
storeFilter.value === "both" ? ["spark", "apm"] : [storeFilter.value];
|
storeFilter.value === "both" ? ["spark", "apm"] : [storeFilter.value];
|
||||||
const newTabCategories: Record<string, Record<string, CategoryInfo>> = {};
|
const newTabCategories: Record<string, Record<string, CategoryInfo>> = {};
|
||||||
|
|
||||||
for (const entry of sidebarEntries.value) {
|
// 并行加载所有侧边栏入口的子分类,减少串行等待
|
||||||
if (entry.type !== "category") continue;
|
const categoryEntries = sidebarEntries.value.filter(
|
||||||
const folderName = entry.value || entry.id;
|
(e) => e.type === "category",
|
||||||
const catData: Record<string, { zh: string; origins: string[] }> = {};
|
);
|
||||||
|
|
||||||
for (const mode of modes) {
|
await Promise.all(
|
||||||
const finalArch = mode === "spark" ? `${arch}-store` : `${arch}-apm`;
|
categoryEntries.map(async (entry) => {
|
||||||
const path = `/${finalArch}/${folderName}/categories.json`;
|
const folderName = entry.value || entry.id;
|
||||||
|
const catData: Record<string, { zh: string; origins: string[] }> = {};
|
||||||
|
// 只查询该入口实际存在的来源仓库,避免对不存在目录的 404 重试
|
||||||
|
const entryModes = entry.origins?.length
|
||||||
|
? entry.origins.filter((o) => modes.includes(o))
|
||||||
|
: modes;
|
||||||
|
|
||||||
try {
|
await Promise.all(
|
||||||
const response = await axiosInstance.get(path);
|
entryModes.map(async (mode) => {
|
||||||
const data = response.data;
|
const finalArch = mode === "spark" ? `${arch}-store` : `${arch}-apm`;
|
||||||
Object.keys(data).forEach((key) => {
|
const path = `/${finalArch}/${folderName}/categories.json`;
|
||||||
if (catData[key]) {
|
|
||||||
if (!catData[key].origins.includes(mode)) {
|
try {
|
||||||
catData[key].origins.push(mode);
|
const response = await axiosInstance.get(path);
|
||||||
}
|
const data = response.data;
|
||||||
} else {
|
Object.keys(data).forEach((key) => {
|
||||||
catData[key] = {
|
if (catData[key]) {
|
||||||
zh: data[key].zh || data[key],
|
if (!catData[key].origins.includes(mode)) {
|
||||||
origins: [mode],
|
catData[key].origins.push(mode);
|
||||||
};
|
}
|
||||||
|
} else {
|
||||||
|
catData[key] = {
|
||||||
|
zh: data[key].zh || data[key],
|
||||||
|
origins: [mode],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch {
|
||||||
|
// 该入口没有子分类,静默忽略
|
||||||
}
|
}
|
||||||
});
|
}),
|
||||||
} catch {
|
|
||||||
// 该入口没有子分类,静默忽略
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Object.keys(catData).length > 0) {
|
|
||||||
newTabCategories[entry.id] = catData;
|
|
||||||
logger.info(
|
|
||||||
`入口 "${entry.id}" 加载到 ${Object.keys(catData).length} 个子分类`,
|
|
||||||
);
|
);
|
||||||
}
|
|
||||||
}
|
if (Object.keys(catData).length > 0) {
|
||||||
|
newTabCategories[entry.id] = catData;
|
||||||
|
logger.info(
|
||||||
|
`入口 "${entry.id}" 加载到 ${Object.keys(catData).length} 个子分类`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
tabCategories.value = newTabCategories;
|
tabCategories.value = newTabCategories;
|
||||||
};
|
};
|
||||||
@@ -2609,8 +2628,12 @@ const loadTabApps = async (entryId: string) => {
|
|||||||
loadingTabs.value = new Set(loadingTabs.value).add(entryId);
|
loadingTabs.value = new Set(loadingTabs.value).add(entryId);
|
||||||
|
|
||||||
const arch = window.apm_store.arch || "amd64";
|
const arch = window.apm_store.arch || "amd64";
|
||||||
const modes: Array<"spark" | "apm"> =
|
const allModes: Array<"spark" | "apm"> =
|
||||||
storeFilter.value === "both" ? ["spark", "apm"] : [storeFilter.value];
|
storeFilter.value === "both" ? ["spark", "apm"] : [storeFilter.value];
|
||||||
|
// 只查询该入口实际存在的来源仓库,避免对不存在目录的 404 重试
|
||||||
|
const modes = entry.origins?.length
|
||||||
|
? entry.origins.filter((o) => allModes.includes(o))
|
||||||
|
: allModes;
|
||||||
const folderName = entry.value || entry.id;
|
const folderName = entry.value || entry.id;
|
||||||
const subCats = tabCategories.value[entryId];
|
const subCats = tabCategories.value[entryId];
|
||||||
|
|
||||||
@@ -2803,13 +2826,16 @@ onMounted(async () => {
|
|||||||
|
|
||||||
await loadTabCategories();
|
await loadTabCategories();
|
||||||
|
|
||||||
// 分类目录加载后,并行加载主页数据和所有应用列表
|
// 先启动侧边栏入口预加载,让其请求优先进入网络队列
|
||||||
// 使用非阻塞方式加载,让UI先展示出来
|
// 避免被「全部应用」的大量并发请求抢占连接池
|
||||||
|
const sidebarPreloadPromise = preloadSidebarTabApps();
|
||||||
|
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
homeLoading.value = true;
|
homeLoading.value = true;
|
||||||
|
|
||||||
// 启动加载任务,但不等待它们完成
|
// 侧边栏入口预加载先启动,全部应用和主页数据随后并行加载
|
||||||
Promise.all([
|
Promise.all([
|
||||||
|
sidebarPreloadPromise,
|
||||||
loadHome(),
|
loadHome(),
|
||||||
new Promise<void>((resolve) => {
|
new Promise<void>((resolve) => {
|
||||||
loadApps(() => {
|
loadApps(() => {
|
||||||
@@ -2817,8 +2843,6 @@ onMounted(async () => {
|
|||||||
resolve();
|
resolve();
|
||||||
});
|
});
|
||||||
}),
|
}),
|
||||||
// 并行预加载所有侧边栏入口的应用数据
|
|
||||||
preloadSidebarTabApps(),
|
|
||||||
]).then(() => {
|
]).then(() => {
|
||||||
// 所有数据加载完成后的回调(可选)
|
// 所有数据加载完成后的回调(可选)
|
||||||
logger.info("所有应用数据加载完成");
|
logger.info("所有应用数据加载完成");
|
||||||
|
|||||||
@@ -243,6 +243,8 @@ export interface SidebarEntry {
|
|||||||
icon?: string;
|
icon?: string;
|
||||||
type?: "category" | "search" | "link" | "homeList";
|
type?: "category" | "search" | "link" | "homeList";
|
||||||
value?: string;
|
value?: string;
|
||||||
|
/** 哪些来源仓库(spark / apm)包含此入口,用于避免对不存在的仓库发起无效请求 */
|
||||||
|
origins?: Array<"spark" | "apm">;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SparkUser {
|
export interface SparkUser {
|
||||||
|
|||||||
Reference in New Issue
Block a user