完善掉线诊断并优化二维码加载

This commit is contained in:
yml2213
2026-07-14 16:06:25 +08:00
parent 7b2d94e22d
commit 3a555c27b2
12 changed files with 388 additions and 31 deletions
@@ -35,6 +35,10 @@ const previewURLs = ref<string[]>([])
const failed = ref(false)
const createdURLs: string[] = []
const maxConcurrentAuthImageLoads = 6
let activeAuthImageLoads = 0
const authImageLoadQueue: Array<() => void> = []
const usePreview = computed(() => !!props.previewSrcList?.length)
const effectiveAdmin = computed(() => props.admin || isAdminPath(window.location.pathname))
const fallbackText = computed(() => (failed.value ? '图片加载失败' : '图片加载中'))
@@ -42,6 +46,26 @@ const imageStyleValue = computed(() => {
if (!props.fit) return props.imageStyle
return [props.imageStyle, { objectFit: props.fit }]
})
const previewSignature = computed(() => props.previewSrcList?.join('\u0000') || '')
function withAuthImageLoadSlot<T>(task: () => Promise<T>): Promise<T> {
return new Promise((resolve, reject) => {
const run = () => {
activeAuthImageLoads++
task()
.then(resolve, reject)
.finally(() => {
activeAuthImageLoads--
authImageLoadQueue.shift()?.()
})
}
if (activeAuthImageLoads < maxConcurrentAuthImageLoads) {
run()
return
}
authImageLoadQueue.push(run)
})
}
function extractObjectKey(value: string) {
try {
@@ -63,8 +87,9 @@ function shouldFetchAsAdmin(value: string) {
async function resolveURL(url: string): Promise<string> {
if (!url || !shouldFetchWithAuth(url)) return url
const key = extractObjectKey(url)
const blob =
shouldFetchAsAdmin(url) && key ? await fetchAdminFileBlob(key) : await fetchFileBlobByURL(url)
const blob = await withAuthImageLoadSlot(() =>
shouldFetchAsAdmin(url) && key ? fetchAdminFileBlob(key) : fetchFileBlobByURL(url)
)
const blobURL = URL.createObjectURL(blob)
createdURLs.push(blobURL)
return blobURL
@@ -87,18 +112,20 @@ async function loadImage() {
}
try {
imageURL.value = await resolveURL(props.source)
const sourceURL = await resolveURL(props.source)
imageURL.value = sourceURL
if (props.previewSrcList?.length) {
previewURLs.value = await Promise.all(props.previewSrcList.map(resolveURL))
previewURLs.value = await Promise.all(
props.previewSrcList.map(url => (url === props.source ? sourceURL : resolveURL(url)))
)
}
} catch {
failed.value = true
}
}
watch(() => [props.source, effectiveAdmin.value, props.previewSrcList] as const, loadImage, {
watch(() => [props.source, effectiveAdmin.value, previewSignature.value] as const, loadImage, {
immediate: true,
deep: true,
})
onBeforeUnmount(cleanup)