mirror of
https://github.com/Moe-Sakura/frontend.git
synced 2026-04-11 11:23:26 +08:00
* 移除 `vue-router` 依赖,简化项目结构。 * 更新 `package.json` 和 `pnpm-lock.yaml`,确保依赖项的整洁性。 * 优化服务工作者 `sw.js`,引入缓存策略和版本管理,提升 PWA 性能。 * 更新多个组件的样式,增强用户界面的视觉一致性。 * 调整 `vite.config.ts`,引入新的插件以支持服务工作者版本管理。
104 lines
2.6 KiB
Vue
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>
|
|
|