79 lines
3.1 KiB
JavaScript
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;
|
|
}
|
|
};
|