2024-07-29 22:11:22 +08:00
|
|
|
<script setup lang="ts">
|
|
|
|
import { h, onMounted, onUnmounted, ref } from 'vue';
|
|
|
|
|
|
|
|
import { $t } from '@vben/locales';
|
|
|
|
import { ToastAction, useToast } from '@vben-core/shadcn-ui';
|
|
|
|
|
|
|
|
interface Props {
|
|
|
|
// 轮训时间,分钟
|
2024-07-29 23:56:59 +08:00
|
|
|
checkUpdatesInterval?: number;
|
2024-07-29 22:11:22 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
defineOptions({ name: 'CheckUpdates' });
|
|
|
|
|
|
|
|
const props = withDefaults(defineProps<Props>(), {
|
2024-07-29 23:56:59 +08:00
|
|
|
checkUpdatesInterval: 1,
|
2024-07-29 22:11:22 +08:00
|
|
|
});
|
|
|
|
|
|
|
|
const lastVersionTag = ref('');
|
|
|
|
let isCheckingUpdates = false;
|
|
|
|
const timer = ref<ReturnType<typeof setInterval>>();
|
|
|
|
const { toast } = useToast();
|
|
|
|
|
|
|
|
async function getVersionTag() {
|
|
|
|
try {
|
2024-08-01 21:05:31 +08:00
|
|
|
if (
|
|
|
|
location.hostname === 'localhost' ||
|
|
|
|
location.hostname === '127.0.0.1'
|
|
|
|
) {
|
|
|
|
return null;
|
|
|
|
}
|
2024-07-29 22:11:22 +08:00
|
|
|
const response = await fetch('/', {
|
|
|
|
cache: 'no-cache',
|
|
|
|
method: 'HEAD',
|
|
|
|
});
|
|
|
|
|
|
|
|
return (
|
|
|
|
response.headers.get('etag') || response.headers.get('last-modified')
|
|
|
|
);
|
|
|
|
} catch {
|
|
|
|
console.error('Failed to fetch version tag');
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
async function checkForUpdates() {
|
|
|
|
const versionTag = await getVersionTag();
|
|
|
|
if (!versionTag) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 首次运行时不提示更新
|
|
|
|
if (!lastVersionTag.value) {
|
|
|
|
lastVersionTag.value = versionTag;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2024-08-01 21:05:31 +08:00
|
|
|
if (lastVersionTag.value !== versionTag && versionTag) {
|
2024-07-29 22:11:22 +08:00
|
|
|
clearInterval(timer.value);
|
2024-07-29 23:56:59 +08:00
|
|
|
handleNotice(versionTag);
|
2024-07-29 22:11:22 +08:00
|
|
|
}
|
|
|
|
}
|
2024-07-29 23:56:59 +08:00
|
|
|
function handleNotice(versionTag: string) {
|
2024-07-29 22:11:22 +08:00
|
|
|
const { dismiss } = toast({
|
|
|
|
action: h('div', [
|
|
|
|
h(
|
|
|
|
ToastAction,
|
|
|
|
{
|
|
|
|
altText: $t('common.cancel'),
|
|
|
|
onClick: () => dismiss(),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
default: () => $t('common.cancel'),
|
|
|
|
},
|
|
|
|
),
|
|
|
|
h(
|
|
|
|
ToastAction,
|
|
|
|
{
|
|
|
|
altText: $t('common.refresh'),
|
|
|
|
class: 'bg-primary hover:bg-primary-hover mx-1',
|
|
|
|
onClick: () => {
|
2024-07-29 23:56:59 +08:00
|
|
|
lastVersionTag.value = versionTag;
|
2024-07-29 22:11:22 +08:00
|
|
|
window.location.reload();
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
default: () => $t('common.refresh'),
|
|
|
|
},
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
description: $t('widgets.checkUpdatesDescription'),
|
|
|
|
duration: 0,
|
|
|
|
title: $t('widgets.checkUpdatesTitle'),
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
function start() {
|
|
|
|
// 每5分钟检查一次
|
2024-07-29 23:56:59 +08:00
|
|
|
timer.value = setInterval(
|
|
|
|
checkForUpdates,
|
|
|
|
props.checkUpdatesInterval * 60 * 1000,
|
|
|
|
);
|
2024-07-29 22:11:22 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
function handleVisibilitychange() {
|
|
|
|
if (document.hidden) {
|
|
|
|
stop();
|
|
|
|
} else {
|
|
|
|
if (!isCheckingUpdates) {
|
|
|
|
isCheckingUpdates = true;
|
|
|
|
checkForUpdates().finally(() => {
|
|
|
|
isCheckingUpdates = false;
|
|
|
|
start();
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function stop() {
|
|
|
|
clearInterval(timer.value);
|
|
|
|
}
|
|
|
|
|
|
|
|
onMounted(() => {
|
|
|
|
start();
|
|
|
|
document.addEventListener('visibilitychange', handleVisibilitychange);
|
|
|
|
});
|
|
|
|
|
|
|
|
onUnmounted(() => {
|
|
|
|
stop();
|
|
|
|
document.removeEventListener('visibilitychange', handleVisibilitychange);
|
|
|
|
});
|
|
|
|
</script>
|
|
|
|
<template>
|
|
|
|
<slot></slot>
|
|
|
|
</template>
|