Files
SMANAGE/TempLate/GERP/assets/gerp/GERPThemeSync.js
T

79 lines
3.1 KiB
JavaScript

/**
* GERPThemeSync.js - 全局主题同步模块
* 这个模块独立运行,让所有子页面都能自动获得主题同步功能
*/
window.GERPThemeSync = {
// 初始化主题同步
init() {
const root = document.documentElement;
// 从localStorage读取并应用保存的主题
this.applySavedTheme();
// 监听来自父页面的主题变化消息
window.addEventListener('message', (e) => {
const { type, data } = e.data || {};
if (type === 'THEME_CHANGE' && data && data.colors) {
Object.entries(data.colors).forEach(([key, value]) => {
root.style.setProperty(`--${key}`, value);
});
// 保存到localStorage
localStorage.setItem('gerp-theme', data.theme);
localStorage.setItem('gerp-theme-colors', JSON.stringify(data.colors));
}
if (type === 'THEME_RESPONSE' && data && data.colors) {
Object.entries(data.colors).forEach(([key, value]) => {
root.style.setProperty(`--${key}`, value);
});
// 保存到localStorage
localStorage.setItem('gerp-theme', data.theme);
localStorage.setItem('gerp-theme-colors', JSON.stringify(data.colors));
}
});
// 页面加载时向父页面请求当前主题
if (window.parent && window.parent !== window) {
window.parent.postMessage({ type: 'GET_THEME' }, '*');
}
},
// 应用保存的主题
applySavedTheme() {
const root = document.documentElement;
const themeColors = localStorage.getItem('gerp-theme-colors');
if (themeColors) {
try {
const colors = JSON.parse(themeColors);
// 向后兼容:旧主题数据可能缺少 HoverBackground,根据 BackgroundColor 亮度推断并回填
// 深色背景用白色 8% 透明(hover 变浅),浅色背景用黑色 4% 透明
if (!colors.HoverBackground && colors.BackgroundColor) {
colors.HoverBackground = this.IsColorDark(colors.BackgroundColor)
? 'rgba(255, 255, 255, 0.08)'
: 'rgba(0, 0, 0, 0.04)';
localStorage.setItem('gerp-theme-colors', JSON.stringify(colors));
}
Object.entries(colors).forEach(([key, value]) => {
root.style.setProperty(`--${key}`, value);
});
} catch (e) {
console.warn('无法解析主题颜色:', e);
}
}
},
// 辅助:判断颜色亮度(YIQ 公式),<128 视为深色
IsColorDark(Hex) {
if (!Hex || typeof Hex !== 'string') return false;
const M = Hex.replace('#', '').trim();
if (M.length !== 6) return false;
const R = parseInt(M.substr(0, 2), 16);
const G = parseInt(M.substr(2, 2), 16);
const B = parseInt(M.substr(4, 2), 16);
if (isNaN(R) || isNaN(G) || isNaN(B)) return false;
return (R * 299 + G * 587 + B * 114) / 1000 < 128;
}
};