Files
zyt/admin/src/hooks/useDesktopWorkstationDownloads.ts
T

60 lines
2.4 KiB
TypeScript

import { onMounted, onUnmounted, ref, shallowRef } from 'vue'
import {
getDesktopWorkstationDownloads,
type DesktopWorkstationDownload,
type DesktopWorkstationDownloads
} from '@/api/setting/desktop_workstation'
// 接诊台、列表和聊天窗口共用一个请求与短缓存。
const downloads = shallowRef<DesktopWorkstationDownloads>({ version: '', packages: [] })
const downloadsLoading = ref(false)
const downloadsFailed = ref(false)
let pending: Promise<void> | undefined
let loadedAt = 0
const CACHE_MS = 5 * 60 * 1000
export function normalizeDesktopDownloads(value: DesktopWorkstationDownloads): DesktopWorkstationDownloads {
const platforms = ['windows_x64', 'macos_arm64', 'macos_x64']
const packages: DesktopWorkstationDownload[] = []
const seen = new Set<string>()
for (const item of Array.isArray(value?.packages) ? value.packages : []) {
if (!item || typeof item !== 'object') continue
if (!platforms.includes(item.platform) || seen.has(item.platform)) continue
try {
const url = new URL(item.url)
if (!['https:', 'http:'].includes(url.protocol) || url.username || url.password) continue
if (!/^[a-f\d]{64}$/i.test(item.sha256)) continue
packages.push({ ...item, url: url.href })
seen.add(item.platform)
} catch { /* 配置异常时不生成无效下载链接。 */ }
}
return { version: String(value?.version || ''), packages }
}
export function useDesktopWorkstationDownloads() {
const loadDownloads = (force = false): Promise<void> => {
if (pending) return pending
if (!force && loadedAt > 0 && Date.now() - loadedAt < CACHE_MS) return Promise.resolve()
downloadsLoading.value = true
downloadsFailed.value = false
pending = getDesktopWorkstationDownloads().then(data => {
downloads.value = normalizeDesktopDownloads(data)
loadedAt = Date.now()
}).catch(() => {
downloadsFailed.value = true
}).finally(() => {
downloadsLoading.value = false
pending = undefined
})
return pending
}
const refreshOnFocus = () => { void loadDownloads() }
onMounted(() => {
void loadDownloads()
window.addEventListener('focus', refreshOnFocus)
})
onUnmounted(() => window.removeEventListener('focus', refreshOnFocus))
return { downloads, downloadsLoading, downloadsFailed, loadDownloads }
}