mirror of
https://gitee.com/spark-store-project/spark-store
synced 2026-09-20 13:40:11 +08:00
fix: 应用截图按实际存在数量预览,不再固定 5 张
- useAppDetail.loadScreenshots 改为异步探测:并发 HEAD 请求 screen_1~5.png, 仅把返回 2xx 的真实截图加入 screenshots,不足 5 张时预览计数与按钮边界自动跟随 - ScreenPreview 已有的 disabled 边界 (currentScreenIndex === screenshots.length-1) 因此生效,切换到最后一张后禁止继续向后,消除空白页 - 新增 screenshotAbortController:打开新详情/关闭详情时取消旧探测,避免结果覆盖 - 探测异常不影响详情页弹窗,截图区域在探测完成后自动刷新/显示暂无应用截图 - debian/changelog 测试版本号 5.2.1.3-test - 验证:vue-tsc 0 / eslint 0 / dpkg-buildpackage 打包成功
This commit is contained in:
Vendored
+1
-1
@@ -1,4 +1,4 @@
|
||||
spark-store (5.2.1.2-test) UNRELEASED; urgency=medium
|
||||
spark-store (5.2.1.3-test) UNRELEASED; urgency=medium
|
||||
|
||||
* Initial release. (Closes: #nnnn) <nnnn is the bug number of your ITP>
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@ import {
|
||||
buildReviewTags,
|
||||
} from "../modules/appIdentity";
|
||||
import { loadFavoriteMetadataForDetail } from "./useFavorites";
|
||||
import { axiosInstance } from "./useHttp";
|
||||
import type { ReviewTags } from "../global/typedefinition";
|
||||
import type { Ref } from "vue";
|
||||
|
||||
@@ -54,6 +55,9 @@ const currentReviewTags = computed<ReviewTags | null>(() => {
|
||||
});
|
||||
});
|
||||
|
||||
// 截图探测请求的中断控制器:每次打开新详情前取消旧探测,避免结果覆盖当前应用。
|
||||
let screenshotAbortController: AbortController | null = null;
|
||||
|
||||
// 从仓库获取应用详细信息的辅助函数
|
||||
const fetchAppFromStore = async (
|
||||
pkgname: string,
|
||||
@@ -329,7 +333,10 @@ const openDetail = async (app: App | OpenDetailInput) => {
|
||||
|
||||
currentApp.value = finalApp;
|
||||
currentScreenIndex.value = 0;
|
||||
loadScreenshots(displayAppForScreenshots);
|
||||
// 截图异步探测,详情页先弹出不阻塞;探测完成后截图区域自动刷新
|
||||
loadScreenshots(displayAppForScreenshots).catch(() => {
|
||||
// 异常(含取消)已在 loadScreenshots 内处理,此处仅避免未捕获 promise
|
||||
});
|
||||
showModal.value = true;
|
||||
|
||||
currentAppSparkInstalled.value = false;
|
||||
@@ -386,19 +393,60 @@ const checkAppInstalled = (app: App) => {
|
||||
}
|
||||
};
|
||||
|
||||
const loadScreenshots = (app: App) => {
|
||||
// 探测单张截图是否真实存在:用 HEAD 请求,超时 3s,仅当返回 2xx 时视为有效。
|
||||
// 使用 axiosInstance 以便复用同源配置,但 HEAD PNG 不会触发 .json 缓存穿透拦截器。
|
||||
const checkScreenshotExists = async (
|
||||
url: string,
|
||||
signal?: AbortSignal,
|
||||
): Promise<boolean> => {
|
||||
try {
|
||||
await axiosInstance.head(url, { timeout: 3000, signal });
|
||||
return true;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
const loadScreenshots = async (app: App) => {
|
||||
// 取消上一应用的截图探测,避免结果覆盖到当前应用
|
||||
if (screenshotAbortController) {
|
||||
screenshotAbortController.abort();
|
||||
}
|
||||
const controller = new AbortController();
|
||||
screenshotAbortController = controller;
|
||||
|
||||
screenshots.value = [];
|
||||
if (!app.category || app.category === "unknown") return;
|
||||
const arch = window.apm_store.arch || "amd64";
|
||||
const finalArch = app.origin === "spark" ? `${arch}-store` : `${arch}-apm`;
|
||||
|
||||
const candidates: string[] = [];
|
||||
for (let i = 1; i <= 5; i++) {
|
||||
const screenshotUrl = `${APM_STORE_BASE_URL}/${finalArch}/${app.category}/${app.pkgname}/screen_${i}.png`;
|
||||
screenshots.value.push(screenshotUrl);
|
||||
candidates.push(
|
||||
`${APM_STORE_BASE_URL}/${finalArch}/${app.category}/${app.pkgname}/screen_${i}.png`,
|
||||
);
|
||||
}
|
||||
|
||||
try {
|
||||
// 并发探测 5 张候选截图,只保留真实存在的;失败视为无该图,不阻塞详情页打开。
|
||||
const results = await Promise.all(
|
||||
candidates.map((url) => checkScreenshotExists(url, controller.signal)),
|
||||
);
|
||||
const valid = candidates.filter((_, index) => results[index]);
|
||||
screenshots.value = valid;
|
||||
} catch {
|
||||
// 当前轮次被新详情页取消或异常:不写入旧结果
|
||||
}
|
||||
};
|
||||
|
||||
const closeDetail = () => {
|
||||
showModal.value = false;
|
||||
currentApp.value = null;
|
||||
// 关闭详情时取消正在进行的截图探测,避免结果写入已关闭的旧应用
|
||||
if (screenshotAbortController) {
|
||||
screenshotAbortController.abort();
|
||||
screenshotAbortController = null;
|
||||
}
|
||||
};
|
||||
|
||||
const openScreenPreview = (index: number) => {
|
||||
|
||||
Reference in New Issue
Block a user