Files
dax-pay-h5/index.html
bootx 0da879ee86 feat(h5): 接入站点配置展示与本地缓存
启动时缓存优先 apply,远程 contentHash 一致则跳过。
首页展示 Logo/系统名与版权备案联系方式;favicon 受控更新。
lint-staged 限定为源码后缀,避免对图片跑 eslint。
2026-07-14 10:45:29 +08:00

150 lines
4.7 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!doctype html>
<html lang="zh-cmn-Hans" id="htmlRoot">
<head>
<meta charset="UTF-8" />
<!-- id 固定, 由 init-website-config 受控更新; 禁止空 href -->
<link id="favicon" rel="icon" type="image/svg+xml" href="/logo.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title><%= title %></title>
</head>
<body>
<div id="app">
<script>
;(() => {
// 设备类型探测:移动端 UA含 iPadOS 13+ 伪装桌面 UA 的情况)判定为 mobile其余为 pc
// 开发期可用 ?device=pc|mobile 查询参数强制覆盖,便于切端调试
const params = new URLSearchParams(window.location.search)
const override = params.get('device')
const ua = navigator.userAgent
const isTouch = navigator.maxTouchPoints > 0
const isMobileUA =
/(Mobile|Android|iPhone|iPod|Windows Phone)/i.test(ua) || (isTouch && /Macintosh/i.test(ua))
window.__DEVICE__ = override === 'pc' || override === 'mobile' ? override : isMobileUA ? 'mobile' : 'pc'
// PC 端只挂载 #pc-app隐藏 #app 内的移动端首屏 loading避免残留转圈
if (window.__DEVICE__ === 'pc') {
const appEl = document.getElementById('app')
if (appEl) appEl.style.display = 'none'
}
// 主题色从本地存储读取(用户可配置项持久化)
const { appTheme = '#5d9dfe' } = JSON.parse(window.localStorage.getItem('DESIGN-SETTING')) || {}
// 首屏主题:跟随系统 prefers-color-scheme无法识别时默认浅色
let theme = 'light'
if (typeof window.matchMedia === 'function') {
theme = window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'
}
const htmlRoot = document.getElementById('htmlRoot')
if (htmlRoot) {
htmlRoot.classList.add(theme)
}
// 设置主题色变量
document.documentElement.style.setProperty('--app-theme-color', appTheme)
})()
</script>
<style>
body {
margin: 0;
}
html.dark .first-loading-wrap {
background-color: #1c1c1e;
}
.first-loading-wrap {
display: flex;
width: 100%;
height: 100vh;
justify-content: center;
align-items: center;
flex-direction: column;
}
.first-loading-wrap > h1 {
font-size: 28px;
}
.first-loading-wrap .loading-wrap {
padding: 98px;
display: flex;
justify-content: center;
align-items: center;
}
.dot {
animation: antRotate 1.2s infinite linear;
transform: rotate(45deg);
position: relative;
display: inline-block;
font-size: 12px;
width: 30px;
height: 30px;
box-sizing: border-box;
}
.dot i {
width: 14px;
height: 14px;
position: absolute;
display: block;
background: var(--app-theme-color);
border-radius: 100%;
transform: scale(0.75);
transform-origin: 50% 50%;
opacity: 0.3;
animation: antSpinMove 1s infinite linear alternate;
}
.dot i:nth-child(1) {
top: 0;
left: 0;
}
.dot i:nth-child(2) {
top: 0;
right: 0;
-webkit-animation-delay: 0.4s;
animation-delay: 0.4s;
}
.dot i:nth-child(3) {
right: 0;
bottom: 0;
-webkit-animation-delay: 0.8s;
animation-delay: 0.8s;
}
.dot i:nth-child(4) {
bottom: 0;
left: 0;
-webkit-animation-delay: 1.2s;
animation-delay: 1.2s;
}
@keyframes antRotate {
to {
-webkit-transform: rotate(405deg);
transform: rotate(405deg);
}
}
@-webkit-keyframes antRotate {
to {
-webkit-transform: rotate(405deg);
transform: rotate(405deg);
}
}
@keyframes antSpinMove {
to {
opacity: 1;
}
}
@-webkit-keyframes antSpinMove {
to {
opacity: 1;
}
}
</style>
<div class="first-loading-wrap">
<div class="loading-wrap">
<span class="dot dot-spin"><i></i><i></i><i></i><i></i></span>
</div>
</div>
</div>
<!-- PC 端挂载点(与移动端 #app 并列,同一时刻仅其一被挂载) -->
<div id="pc-app"></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>