Files
offerpai_web/src/plugins/remAdapt.ts
T
2026-08-11 11:54:35 +08:00

119 lines
4.9 KiB
TypeScript
Raw 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.
/**
* REM 适配插件
* 以 1920px 设计稿为基准,1rem = 100px
* 小屏使用 transform scale 缩放,同时设置 CSS 变量 --vh 供页面使用真实视口高度
*/
import type { Plugin } from 'vue'
const remAdaptPlugin: Plugin = {
install() {
const docEl = document.documentElement
const designWidth = 1920
// 检测是否为移动端/小屏
const isMobile = (): boolean => {
return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)
|| window.innerWidth < 1200
}
// 重新计算缩放
const recalc = () => {
const clientWidth = docEl.clientWidth
if (!clientWidth) return
// 始终使用 100px 作为基准
docEl.style.fontSize = '100px'
const body = document.body
if (!body) return
if (isMobile()) {
// 移动端首页(/m):不使用 scale 缩放,直接以移动端原生尺寸渲染
const isMobileHome = window.location.pathname === '/m'
if (isMobileHome) {
body.style.width = ''
body.style.height = ''
body.style.minHeight = ''
body.style.overflowY = ''
body.style.transform = ''
body.style.transformOrigin = ''
docEl.style.height = ''
docEl.style.overflow = ''
// 移动端首页 1rem = 视口宽度 / 3.90(设计稿 390px
const mobileFontSize = clientWidth / 3.90
docEl.style.fontSize = mobileFontSize + 'px'
docEl.style.setProperty('--app-height', '100vh')
docEl.style.setProperty('--chat-width', '100%')
return
}
// 其他页面:使用 transform scale 缩放整个页面
const scale = clientWidth / designWidth
body.style.width = designWidth + 'px'
body.style.transform = `scale(${scale})`
body.style.transformOrigin = 'top left'
// 屏幕越小 scale 越小,适当增大 rem 基准让字体视觉上更大
// 首页和其他页面使用不同的缩放系数
const isHomePage = window.location.pathname === '/' || window.location.pathname === '/index.html' || window.location.pathname === '/m'
const homeMultiplier = 0.6 // 首页字体放大系数,可单独调整
const otherMultiplier = 2.0 // 其他页面字体放大系数
const multiplier = isHomePage ? homeMultiplier : otherMultiplier
const homeMaxFontSize = 180 // 首页最大 fontSize 上限
const otherMaxFontSize = 630 // 其他页面最大 fontSize 上限
const maxFontSize = isHomePage ? homeMaxFontSize : otherMaxFontSize
const fontScale = 1 + (1 - scale) * multiplier
const fontSize = Math.min(100 * fontScale, maxFontSize)
docEl.style.fontSize = fontSize + 'px'
// 动态计算聊天面板宽度:屏幕越窄,宽度从 4rem 缩到 1.0rem
// 用 scale 直接驱动(scale=0.625 时满宽4remscale 越小宽度越小)
const chatWidth = 1.0 + (4.0 - 1.0) * scale // scale=1→4rem, scale=0.5→2.5rem, scale=0.3→1.9rem
docEl.style.setProperty('--chat-width', Math.max(chatWidth, 1.0).toFixed(2) + 'rem')
// 小屏导航宽度CSS变量
docEl.style.setProperty('--nav-width', '0.8rem')
// body 高度 = 视口高度 / scale,使其缩放后刚好等于视口高度
// overflow-y: auto 让内容在 body 内部滚动
const realViewHeight = window.innerHeight / scale
body.style.height = realViewHeight + 'px'
body.style.overflowY = 'auto'
body.style.minHeight = ''
// 设置 CSS 变量让页面组件可以使用真实视口高度(设计稿尺度下)
docEl.style.setProperty('--app-height', realViewHeight + 'px')
// html 固定视口高度 + overflow hidden,裁剪 body 缩放后的布局占位
docEl.style.height = '100vh'
docEl.style.overflow = 'hidden'
} else {
// PC 端:移除缩放相关样式
body.style.width = ''
body.style.height = ''
body.style.minHeight = ''
body.style.overflowY = ''
body.style.transform = ''
body.style.transformOrigin = ''
docEl.style.height = ''
docEl.style.overflow = ''
docEl.style.setProperty('--app-height', '100vh')
docEl.style.setProperty('--chat-width', '3.6rem')
// 根据窗口宽度设置导航栏宽度CSS变量
const navWidth = window.innerWidth < 1440 ? '0.8rem' : '2.2rem'
docEl.style.setProperty('--nav-width', navWidth)
}
}
// 监听窗口变化
window.addEventListener('resize', recalc, false)
window.addEventListener('orientationchange', recalc, false)
// 初始执行,延迟确保 DOM 加载完成
if (document.readyState === 'complete') {
recalc()
} else {
window.addEventListener('load', recalc)
}
}
}
export default remAdaptPlugin