diff --git a/build/plugins/html.ts b/build/plugins/html.ts new file mode 100644 index 000000000..b94d24fea --- /dev/null +++ b/build/plugins/html.ts @@ -0,0 +1,13 @@ +import type { Plugin } from 'vite'; + +export function setupHtmlPlugin(buildTime: string) { + const plugin: Plugin = { + name: 'html-plugin', + apply: 'build', + transformIndexHtml(html) { + return html.replace('
', `\n `); + } + }; + + return plugin; +} diff --git a/build/plugins/index.ts b/build/plugins/index.ts index d437da70d..debec6782 100644 --- a/build/plugins/index.ts +++ b/build/plugins/index.ts @@ -6,8 +6,9 @@ import progress from 'vite-plugin-progress'; import { setupElegantRouter } from './router'; import { setupUnocss } from './unocss'; import { setupUnplugin } from './unplugin'; +import { setupHtmlPlugin } from './html'; -export function setupVitePlugins(viteEnv: Env.ImportMeta) { +export function setupVitePlugins(viteEnv: Env.ImportMeta, buildTime: string) { const plugins: PluginOption = [ vue({ script: { @@ -19,7 +20,8 @@ export function setupVitePlugins(viteEnv: Env.ImportMeta) { setupElegantRouter(), setupUnocss(viteEnv), ...setupUnplugin(viteEnv), - progress() + progress(), + setupHtmlPlugin(buildTime) ]; return plugins; diff --git a/src/locales/langs/en-us.ts b/src/locales/langs/en-us.ts index 81508a56f..570620e9d 100644 --- a/src/locales/langs/en-us.ts +++ b/src/locales/langs/en-us.ts @@ -1,6 +1,10 @@ const local: App.I18n.Schema = { system: { - title: 'SoybeanAdmin' + title: 'SoybeanAdmin', + updateTitle: 'System Version Update Notification', + updateContent: 'A new version of the system has been detected. Do you want to refresh the page immediately?', + updateConfirm: 'Refresh immediately', + updateCancel: 'Later' }, common: { action: 'Action', diff --git a/src/locales/langs/zh-cn.ts b/src/locales/langs/zh-cn.ts index f5ba30e40..fc01bb658 100644 --- a/src/locales/langs/zh-cn.ts +++ b/src/locales/langs/zh-cn.ts @@ -1,6 +1,10 @@ const local: App.I18n.Schema = { system: { - title: 'Soybean 管理系统' + title: 'Soybean 管理系统', + updateTitle: '系统版本更新通知', + updateContent: '检测到系统有新版本发布,是否立即刷新页面?', + updateConfirm: '立即刷新', + updateCancel: '稍后再说' }, common: { action: '操作', diff --git a/src/main.ts b/src/main.ts index efb97f894..b97a0d936 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,6 +1,6 @@ import { createApp } from 'vue'; import './plugins/assets'; -import { setupDayjs, setupIconifyOffline, setupLoading, setupNProgress } from './plugins'; +import { setupAppVersionNotification, setupDayjs, setupIconifyOffline, setupLoading, setupNProgress } from './plugins'; import { setupStore } from './store'; import { setupRouter } from './router'; import { setupI18n } from './locales'; @@ -23,6 +23,8 @@ async function setupApp() { setupI18n(app); + setupAppVersionNotification(); + app.mount('#app'); } diff --git a/src/plugins/app.ts b/src/plugins/app.ts new file mode 100644 index 000000000..e91fb2c68 --- /dev/null +++ b/src/plugins/app.ts @@ -0,0 +1,51 @@ +import { h } from 'vue'; +import { NButton } from 'naive-ui'; +import { $t } from '../locales'; + +export function setupAppVersionNotification() { + document.addEventListener('visibilitychange', async () => { + const buildTime = await getHtmlBuildTime(); + + if (buildTime !== BUILD_TIME && document.visibilityState === 'visible') { + const n = window.$notification?.create({ + title: $t('system.updateTitle'), + content: $t('system.updateContent'), + action() { + return h('div', { style: { display: 'flex', justifyContent: 'end', gap: '12px', width: '325px' } }, [ + h( + NButton, + { + onClick() { + n?.destroy(); + } + }, + $t('system.updateCancel') + ), + h( + NButton, + { + type: 'primary', + onClick() { + location.reload(); + } + }, + $t('system.updateConfirm') + ) + ]); + } + }); + } + }); +} + +async function getHtmlBuildTime() { + const res = await fetch('/index.html'); + + const html = await res.text(); + + const match = html.match(//); + + const buildTime = match ? match[1] : ''; + + return buildTime; +} diff --git a/src/plugins/index.ts b/src/plugins/index.ts index 5d10c3aac..b2c9f9b55 100644 --- a/src/plugins/index.ts +++ b/src/plugins/index.ts @@ -2,3 +2,4 @@ export * from './loading'; export * from './nprogress'; export * from './iconify'; export * from './dayjs'; +export * from './app'; diff --git a/src/typings/app.d.ts b/src/typings/app.d.ts index e1b4b1eed..035fd8f1a 100644 --- a/src/typings/app.d.ts +++ b/src/typings/app.d.ts @@ -251,6 +251,10 @@ declare namespace App { type Schema = { system: { title: string; + updateTitle: string; + updateContent: string; + updateConfirm: string; + updateCancel: string; }; common: { action: string; diff --git a/vite.config.ts b/vite.config.ts index 1393de1eb..c3ea6d064 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -25,7 +25,7 @@ export default defineConfig(configEnv => { } } }, - plugins: setupVitePlugins(viteEnv), + plugins: setupVitePlugins(viteEnv, buildTime), define: { BUILD_TIME: JSON.stringify(buildTime) },