feat: ✨ 加版本检查功能
This commit is contained in:
@@ -15,6 +15,7 @@
|
||||
import { useAppStore, useSettingsStore } from "@/stores";
|
||||
import { appConfig } from "@/settings";
|
||||
import { ThemeMode, ComponentSize } from "@/enums";
|
||||
import { useVersionCheck } from "@/composables/useVersionCheck";
|
||||
|
||||
const appStore = useAppStore();
|
||||
const settingsStore = useSettingsStore();
|
||||
@@ -30,4 +31,9 @@ const fontColor = computed(() => {
|
||||
? "rgba(255, 255, 255, .15)"
|
||||
: "rgba(0, 0, 0, .15)";
|
||||
});
|
||||
|
||||
// 初始化版本检查
|
||||
if (!import.meta.env.DEV) {
|
||||
useVersionCheck(5 * 60_000);
|
||||
}
|
||||
</script>
|
||||
|
||||
66
src/composables/useVersionCheck.ts
Normal file
66
src/composables/useVersionCheck.ts
Normal file
@@ -0,0 +1,66 @@
|
||||
import { ElNotification } from "element-plus";
|
||||
import { onMounted, onUnmounted, ref } from "vue";
|
||||
|
||||
/** 版本检查 */
|
||||
export function useVersionCheck(interval = 60_000) {
|
||||
const hasNewVersion = ref(false);
|
||||
let notified = false;
|
||||
const safeInterval = Math.max(10_000, interval);
|
||||
|
||||
const checkVersion = async () => {
|
||||
try {
|
||||
const base = import.meta.env.BASE_URL;
|
||||
const baseUrl = base.endsWith("/") ? base : `${base}/`;
|
||||
// 时间戳防 CDN/代理缓存,no-cache 防浏览器磁盘缓存
|
||||
const res = await fetch(`${baseUrl}version.json?t=${Date.now()}`, {
|
||||
cache: "no-cache",
|
||||
});
|
||||
if (!res.ok) return; // 非核心功能,网络异常不影响正常使用
|
||||
|
||||
const data = await res.json();
|
||||
if (data.version && data.version !== __APP_INFO__.buildTimestamp) {
|
||||
hasNewVersion.value = true;
|
||||
showUpdateNotice();
|
||||
}
|
||||
} catch (e) {
|
||||
console.warn("版本检测失败", e);
|
||||
}
|
||||
};
|
||||
|
||||
const showUpdateNotice = () => {
|
||||
if (notified) return;
|
||||
notified = true;
|
||||
|
||||
// 使用 Notification 而非 Modal,不打断用户操作
|
||||
ElNotification({
|
||||
title: "🎉 发现新版本",
|
||||
message: "系统已更新,点击刷新以获取最新功能",
|
||||
duration: 0, // 不自动关闭
|
||||
position: "bottom-right",
|
||||
onClick: () => window.location.reload(),
|
||||
onClose: () => {
|
||||
notified = false;
|
||||
},
|
||||
customClass: "version-update-notice",
|
||||
});
|
||||
};
|
||||
|
||||
let timer: ReturnType<typeof setInterval>;
|
||||
// 用户从其他标签页切回时立即检测,无需等待下一次轮询
|
||||
const handleVisibilityChange = () => {
|
||||
if (!document.hidden) checkVersion();
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
checkVersion();
|
||||
timer = setInterval(checkVersion, safeInterval);
|
||||
document.addEventListener("visibilitychange", handleVisibilityChange);
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
clearInterval(timer);
|
||||
document.removeEventListener("visibilitychange", handleVisibilityChange);
|
||||
});
|
||||
|
||||
return { hasNewVersion };
|
||||
}
|
||||
@@ -9,7 +9,8 @@ import { ElementPlusResolver } from "unplugin-vue-components/resolvers";
|
||||
import { mockDevServerPlugin } from "vite-plugin-mock-dev-server";
|
||||
|
||||
import UnoCSS from "unocss/vite";
|
||||
import { resolve } from "path";
|
||||
import { join, resolve } from "path";
|
||||
import { existsSync, mkdirSync, writeFileSync } from "fs";
|
||||
import { name, version } from "./package.json" with { type: "json" };
|
||||
|
||||
// 平台名称、版本信息
|
||||
@@ -85,6 +86,20 @@ export default defineConfig(({ mode }: ConfigEnv): UserConfig => {
|
||||
dts: false,
|
||||
//dts: "types/components.d.ts",
|
||||
}),
|
||||
// 生成版本号文件
|
||||
{
|
||||
name: "dist-version",
|
||||
closeBundle() {
|
||||
const distDir = resolve(__dirname, "dist");
|
||||
if (!existsSync(distDir)) {
|
||||
mkdirSync(distDir, { recursive: true });
|
||||
}
|
||||
writeFileSync(
|
||||
join(distDir, "version.json"),
|
||||
JSON.stringify({ version: __APP_INFO__.buildTimestamp })
|
||||
);
|
||||
},
|
||||
},
|
||||
] as PluginOption[],
|
||||
// 预加载项目必需的依赖
|
||||
optimizeDeps: {
|
||||
|
||||
Reference in New Issue
Block a user