feat: webAddress

This commit is contained in:
2026-03-16 14:11:01 +08:00
parent b82c35f8b7
commit 8eff97a3f2
7 changed files with 73 additions and 129 deletions

View File

@@ -1,92 +0,0 @@
import { ref } from 'vue'
export const useWebsiteTitle = () => {
const titles = ref<Map<string, string>>(new Map())
const loading = ref(new Set<string>())
const errors = ref(new Map<string, string>())
// 新增:重试配置
const MAX_RETRY = 3
const BASE_DELAY = 800 // 毫秒
const getCache = (url: string) => {
const cached = sessionStorage.getItem(`title_cache_${url}`)
if (!cached) return null
const { title, expire } = JSON.parse(cached)
return Date.now() < expire ? title : null
}
const setCache = (url: string, title: string) => {
const data = { title, expire: Date.now() + 7 * 24 * 60 * 60 * 1000 }
sessionStorage.setItem(`title_cache_${url}`, JSON.stringify(data))
}
const fetchWithRetry = async (url: string, retryCount = 0): Promise<string> => {
const proxyUrl = `https://api.allorigins.win/raw?url=${encodeURIComponent(url)}`
try {
const res = await fetch(proxyUrl)
if (!res.ok) {
throw new Error(`HTTP ${res.status}`)
}
const html = await res.text()
const parser = new DOMParser()
const doc = parser.parseFromString(html, 'text/html')
const title =
doc.querySelector('title')?.textContent?.trim() || new URL(url).hostname || '无标题'
return title
} catch (err) {
if (retryCount >= MAX_RETRY) {
throw err // 达到最大重试次数,抛出错误
}
// 第1次等800ms第2次等1600ms第3次等3200ms
const delay = BASE_DELAY * Math.pow(2, retryCount)
console.warn(
`获取标题失败,${retryCount + 1}/${MAX_RETRY} 次重试,等待 ${delay}ms`,
url
)
await new Promise((resolve) => setTimeout(resolve, delay))
return fetchWithRetry(url, retryCount + 1)
}
}
const fetchTitle = async (url: string): Promise<string> => {
if (titles.value.has(url)) return titles.value.get(url)!
const cached = getCache(url)
if (cached) {
titles.value.set(url, cached)
return cached
}
if (loading.value.has(url)) return ''
loading.value.add(url)
errors.value.delete(url)
try {
const title = await fetchWithRetry(url)
titles.value.set(url, title)
setCache(url, title)
return title
} catch (err) {
const msg = `获取标题失败(已重试 ${MAX_RETRY} 次)`
errors.value.set(url, msg)
console.error(err)
return msg
} finally {
loading.value.delete(url)
}
}
const fetchAll = async (urls: string[]) => {
await Promise.allSettled(urls.map(fetchTitle))
}
return { titles, loading, errors, fetchTitle, fetchAll }
}