Files
web-fusion/src/components/UpdateNotification.vue

124 lines
6.3 KiB
Vue

<template>
<div v-if="isElectronEnv && status !== 'idle'" class="fixed bottom-4 right-4 z-50 animate-slideUp">
<div class="bg-white rounded-xl shadow-2xl border border-gray-200 overflow-hidden w-80">
<!-- 头部 -->
<div class="bg-gradient-to-r from-blue-500 to-blue-600 px-4 py-3 flex items-center justify-between">
<div class="flex items-center gap-2">
<svg class="w-5 h-5 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2"
d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4" />
</svg>
<span class="text-white font-medium">应用更新</span>
</div>
<button @click="dismissUpdate" class="text-white/70 hover:text-white transition-colors">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M6 18L18 6M6 6l12 12" />
</svg>
</button>
</div>
<!-- 内容 -->
<div class="p-4">
<!-- 检查中 -->
<div v-if="status === 'checking'" class="flex items-center gap-3">
<div class="w-5 h-5 border-2 border-blue-500 border-t-transparent rounded-full animate-spin" />
<span class="text-gray-600">正在检查更新...</span>
</div>
<!-- 发现新版本 -->
<div v-if="status === 'available' && updateInfo" class="space-y-3">
<div class="flex items-center justify-between">
<span class="text-gray-500 text-sm">当前版本</span>
<span class="text-gray-700 font-mono text-sm">{{ currentVersion }}</span>
</div>
<div class="flex items-center justify-between">
<span class="text-gray-500 text-sm">最新版本</span>
<span class="text-green-600 font-mono text-sm font-medium">{{ updateInfo.version }}</span>
</div>
<p v-if="updateInfo.releaseNotes" class="text-gray-500 text-xs bg-gray-50 p-2 rounded-lg line-clamp-3">
{{ updateInfo.releaseNotes }}
</p>
<button @click="downloadUpdate"
class="w-full py-2 bg-gradient-to-r from-blue-500 to-blue-600 text-white rounded-lg font-medium hover:from-blue-600 hover:to-blue-700 transition-all shadow-md hover:shadow-lg">
下载更新
</button>
</div>
<!-- 下载中 -->
<div v-if="status === 'downloading' && progress" class="space-y-3">
<div class="flex items-center justify-between text-sm">
<span class="text-gray-600">下载中...</span>
<span class="text-blue-600 font-medium">{{ progress.percent.toFixed(1) }}%</span>
</div>
<div class="h-2 bg-gray-200 rounded-full overflow-hidden">
<div class="h-full bg-gradient-to-r from-blue-500 to-blue-600 transition-all duration-300"
:style="{ width: `${progress.percent}%` }" />
</div>
<div class="flex items-center justify-between text-xs text-gray-500">
<span>{{ formatBytes(progress.transferred) }} / {{ formatBytes(progress.total) }}</span>
<span>{{ formatBytes(progress.bytesPerSecond) }}/s</span>
</div>
</div>
<!-- 下载完成 -->
<div v-if="status === 'downloaded'" class="space-y-3">
<div class="flex items-center gap-2 text-green-600">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M5 13l4 4L19 7" />
</svg>
<span class="font-medium">下载完成</span>
</div>
<p class="text-gray-500 text-sm">点击下方按钮重启应用以完成更新</p>
<button @click="installUpdate"
class="w-full py-2 bg-gradient-to-r from-green-500 to-green-600 text-white rounded-lg font-medium hover:from-green-600 hover:to-green-700 transition-all shadow-md hover:shadow-lg">
🚀 立即重启并安装
</button>
</div>
<!-- 错误 -->
<div v-if="status === 'error'" class="space-y-3">
<div class="flex items-center gap-2 text-red-600">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2"
d="M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
<span class="font-medium">更新失败</span>
</div>
<p class="text-gray-500 text-sm">{{ error }}</p>
<button @click="checkForUpdates"
class="w-full py-2 bg-gray-100 text-gray-700 rounded-lg font-medium hover:bg-gray-200 transition-all">
重试
</button>
</div>
</div>
</div>
</div>
</template>
<script setup>
import { useUpdate } from '../hooks/useUpdate'
import { isElectron } from '../utils/electronBridge'
const isElectronEnv = isElectron()
const {
status,
updateInfo,
progress,
error,
currentVersion,
checkForUpdates,
downloadUpdate,
installUpdate,
dismissUpdate
} = useUpdate()
function formatBytes(bytes) {
if (bytes === 0) return '0 B'
const k = 1024
const sizes = ['B', 'KB', 'MB', 'GB']
const i = Math.floor(Math.log(bytes) / Math.log(k))
return `${(bytes / Math.pow(k, i)).toFixed(1)} ${sizes[i]}`
}
</script>