直接上代码,这里封装为一个组件,项目中直接引用就可以
<template>
<div class="update-tip" v-show="isShowTip">
<div class="box" :class="{ pc: isPC() }">
<div class="title">{{ $t('voc.voc_tishi_0001') }}</div>
<div class="btn" @click="confirmUpdate">{{ $t('voc.voc_tishi_0002') }}</div>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue'
import http from '../../api/index'
import { isPC } from '../../utils/init'
import { useI18n } from 'vue-i18n'
const { t, locale } = useI18n()
const isShowTip = ref<boolean>(false)
// 获取最新的html-text
const getOnlineSrc = async () => {
const data = await http.request<any>({
url: '/index.html?r=' + new Date().getTime(),
method: 'get'
})
const parser = new DOMParser()
const htmlDoc = parser.parseFromString(data, 'text/html')
const onLineSrc = getScriptSrc(htmlDoc.getElementsByTagName('script'))
console.log(htmlDoc, '--', onLineSrc)
return onLineSrc
}
// 获取script的src
const getScriptSrc = (scripts: HTMLCollectionOf<HTMLScriptElement>): string[] => {
const srcArr: string[] = []
// @ts-ignore
for (const element of scripts) {
const type = element.getAttribute('type')
const src = element.getAttribute('src') as string
if (type === 'module' && /^\/assets\//.test(src)) {
srcArr.push(src)
}
}
return srcArr
}
// 对比本地和线上的src标签,地址和位数一致
const contrastSrc = (local: string[], online: string[]) => {
if (local.length != online.length) {
return false
}
console.log(local, '本地')
// 对比
for (const localSrc of local) {
if (!online.some((onlineSrc) => onlineSrc === localSrc)) {
return false
}
}
return true
}
// 更新
const confirmUpdate = () => {
// 刷新页面
location.reload()
}
onMounted(() => {
// 初始化资源缓存判断和弹窗
const localSrc = getScriptSrc(document.getElementsByTagName('script'))
const timer = async () => {
const onLineSrc = await getOnlineSrc()
console.log(onLineSrc, '线上')
const result = contrastSrc(localSrc, onLineSrc)
if (result) {
setTimeout(timer, 1000 * 60 * 1)
} else {
isShowTip.value = true
}
}
timer()
})
</script>
<style scoped lang="less">
.update-tip {
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
background: rgba(0, 0, 0, 0.65);
z-index: 10000008;
.box {
position: absolute;
top: 50%;
left: 35px;
right: 35px;
transform: translate(0, -50%);
background: #fff;
padding: 24px;
&.pc {
left: 50%;
right: none;
padding: 24px;
transform: translate(-50%, -50%);
.title {
padding: 16px 0 40px;
font-size: 15px;
line-height: 20px;
}
.btn {
height: 36px;
font-size: 14px;
line-height: 18px;
}
}
}
.title {
padding: 16px 0 40px;
font-weight: 400;
font-size: 15px;
line-height: 20px;
text-align: center;
}
.btn {
display: flex;
justify-content: center;
align-items: center;
height: 36px;
background: rgba(0, 0, 0, 0.9);
color: #fff;
font-weight: 400;
font-size: 14px;
line-height: 18px;
cursor: pointer;
}
}
</style>