import { ref, onMounted, onUnmounted, computed } from 'vue' import { isElectron } from '../utils/electronBridge' // ============== 单例状态 ============== // 在函数外部定义,确保所有组件共享同一个状态 const status = ref('idle') const updateInfo = ref(null) const progress = ref(null) const error = ref(null) const currentVersion = ref('') const platform = ref('unknown') let listenersSetup = false // 标记是否已设置监听器 let unsubList = [] // 取消订阅列表 const isMac = computed(() => platform.value === 'mac') const isWindows = computed(() => platform.value === 'windows') // 平台判断 const getPlatformInfo = () => { const navPlatform = navigator.platform || '' const ua = navigator.userAgent || '' const appVersion = navigator.appVersion || '' console.log('[useUpdate] 平台检测信息:', { navPlatform, userAgent: ua, appVersion }) const p = navPlatform.toLowerCase() if (p.includes('mac')) return 'mac' if (p.includes('win')) return 'windows' if (p.includes('linux')) return 'linux' const u = ua.toLowerCase() if (u.includes('macintosh') || u.includes('mac os') || u.includes('macintel')) return 'mac' if (u.includes('windows') || u.includes('win32') || u.includes('win64')) return 'windows' if (u.includes('linux')) return 'linux' const av = appVersion.toLowerCase() if (av.includes('mac')) return 'mac' if (av.includes('win')) return 'windows' if (av.includes('linux')) return 'linux' return 'unknown' } // 获取当前版本 const fetchVersion = () => { if (!isElectron()) { currentVersion.value = 'web' return } window.electronAPI.getAppVersion().then(v => { currentVersion.value = v }).catch(console.error) } // 设置监听器(只执行一次) const setupListeners = () => { if (!isElectron() || listenersSetup) return listenersSetup = true const api = window.electronAPI // 正在检查 if (api.onUpdateChecking) { unsubList.push(api.onUpdateChecking(() => { status.value = 'checking' })) } // 发现新版本 unsubList.push(api.onUpdateAvailable((info) => { updateInfo.value = info status.value = 'available' error.value = null })) // 无可用更新 if (api.onUpdateNotAvailable) { unsubList.push(api.onUpdateNotAvailable(() => { status.value = 'idle' })) } unsubList.push(api.onUpdateProgress((prog) => { progress.value = prog status.value = 'downloading' })) unsubList.push(api.onUpdateDownloaded(() => { status.value = 'downloaded' progress.value = null })) unsubList.push(api.onUpdateError((err) => { error.value = err.message status.value = 'error' })) // macOS 手动安装提示 if (api.onUpdateManualInstall) { unsubList.push(api.onUpdateManualInstall((info) => { console.log('macOS 需要手动安装更新:', info.path) alert(`更新已下载完成!\n\n请手动安装更新文件:\n${info.path}\n\n应用将退出。`) })) } } // 清理监听器 const cleanupListeners = () => { unsubList.forEach(unsub => unsub && unsub()) unsubList = [] listenersSetup = false } /** * 应用更新 Hook (Vue Composable) * 单例模式:所有组件共享同一个状态和监听器 * 注意:此 Composable 仅在 Electron 环境中有效 */ export function useUpdate() { // 每个组件挂载时的初始化逻辑 onMounted(() => { // 检测平台(确保只设置一次) if (isElectron() && platform.value === 'unknown') { platform.value = getPlatformInfo() console.log('[useUpdate] 平台检测结果:', platform.value) } fetchVersion() setupListeners() }) // 注意:不在这里清理监听器,因为是单例模式 // 只在最后一个组件卸载时才清理(这里简化处理,不清理) // 如果需要严格清理,可以使用引用计数 const checkForUpdates = () => { if (!isElectron()) return status.value = 'checking' error.value = null window.electronAPI.checkForUpdates().then((hasUpdate) => { if (!hasUpdate) { status.value = 'idle' } }).catch((e) => { error.value = e.message status.value = 'error' }) } const downloadUpdate = () => { if (!isElectron()) return status.value = 'downloading' progress.value = { percent: 0, bytesPerSecond: 0, transferred: 0, total: 0 } window.electronAPI.downloadUpdate().catch((e) => { error.value = e.message status.value = 'error' }) } const installUpdate = () => { if (!isElectron()) return window.electronAPI.installUpdate() } const dismissUpdate = () => { status.value = 'idle' updateInfo.value = null } return { status, updateInfo, progress, error, currentVersion, platform, isMac, isWindows, checkForUpdates, downloadUpdate, installUpdate, dismissUpdate } }