Files
SearcjGal-frontend/src/components/UpdateToast.vue
AdingApkgg 921dd61b59 feat: 更新依赖与优化服务工作者
* 移除 `vue-router` 依赖,简化项目结构。
* 更新 `package.json` 和 `pnpm-lock.yaml`,确保依赖项的整洁性。
* 优化服务工作者 `sw.js`,引入缓存策略和版本管理,提升 PWA 性能。
* 更新多个组件的样式,增强用户界面的视觉一致性。
* 调整 `vite.config.ts`,引入新的插件以支持服务工作者版本管理。
2025-12-14 09:20:15 +08:00

104 lines
2.6 KiB
Vue

<template>
<Transition
enter-active-class="transition-all duration-300 ease-out"
enter-from-class="opacity-0 translate-y-4 scale-95"
enter-to-class="opacity-100 translate-y-0 scale-100"
leave-active-class="transition-all duration-200 ease-in"
leave-from-class="opacity-100 translate-y-0 scale-100"
leave-to-class="opacity-0 translate-y-4 scale-95"
>
<div
v-if="isVisible"
class="fixed bottom-4 left-1/2 -translate-x-1/2 z-[100] px-4 py-3 rounded-2xl bg-gradient-to-r from-[#ff1493] to-[#d946ef] text-white shadow-xl shadow-pink-500/30 flex items-center gap-3 max-w-[90vw] sm:max-w-md"
>
<!-- 图标 -->
<div class="flex-shrink-0 w-8 h-8 rounded-full bg-white/20 flex items-center justify-center">
<RefreshCw :size="18" class="animate-spin" />
</div>
<!-- 文字内容 -->
<div class="flex-1 min-w-0">
<p class="font-semibold text-sm">发现新版本</p>
<p class="text-xs text-white/80 truncate">
{{ countdown > 0 ? `${countdown} 秒后自动更新...` : '正在更新...' }}
</p>
</div>
<!-- 立即更新按钮 -->
<button
v-if="countdown > 0"
class="flex-shrink-0 px-3 py-1.5 rounded-xl bg-white/20 hover:bg-white/30 text-xs font-medium transition-colors"
@click="updateNow"
>
立即更新
</button>
</div>
</Transition>
</template>
<script setup lang="ts">
import { ref, onMounted, onUnmounted } from 'vue'
import { RefreshCw } from 'lucide-vue-next'
import { playPop, playClick, playWhoosh } from '@/composables/useSound'
const props = defineProps<{
isVisible: boolean
onUpdate: () => void
}>()
const countdown = ref(3)
let timer: number | null = null
function updateNow() {
playClick()
countdown.value = 0
playWhoosh()
props.onUpdate()
}
function startCountdown() {
// 先清除可能存在的旧定时器,避免创建多个并发定时器
if (timer) {
clearInterval(timer)
timer = null
}
playPop()
countdown.value = 3
timer = window.setInterval(() => {
countdown.value--
if (countdown.value <= 0) {
if (timer) {
clearInterval(timer)
timer = null
}
props.onUpdate()
}
}, 1000)
}
onMounted(() => {
if (props.isVisible) {
startCountdown()
}
})
onUnmounted(() => {
if (timer) {
clearInterval(timer)
}
})
// 监听 isVisible 变化
import { watch } from 'vue'
watch(() => props.isVisible, (visible) => {
if (visible) {
startCountdown()
} else if (timer) {
clearInterval(timer)
timer = null
}
})
</script>