Files
2026-08-11 19:57:21 +08:00

58 lines
1.9 KiB
JavaScript
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.
/* 主题系统:账户独立主题(dark/light/auto)。
*
* - 后端 GET /api/theme 返回 {mode, effective};auto 已解析为 dark/light
* (按用户经纬度+时区计算日出日落)。
* - 应用方式:html 元素加 .theme-light class(CSS 变量覆盖浅色)。
* - 切换动画:切换瞬间给 html 加 .theme-anim,触发全局 CSS transition
* 平滑渐变,平时无全局 transition(不影响交互反馈)。
* - auto 模式每 5 分钟轮询一次(日落日出边界切换);显示端还会在收到
* SSE theme_changed 时立即刷新。
*/
(function (global) {
'use strict';
var current = 'dark';
var pollTimer = null;
function apply(effective) {
if (!effective) return;
if (effective === current) return;
current = effective;
var root = document.documentElement;
root.classList.add('theme-anim');
root.classList.toggle('theme-light', effective === 'light');
// 过渡结束后移除动画 class,恢复常规交互反馈
setTimeout(function () { root.classList.remove('theme-anim'); }, 600);
}
function fetchTheme(cb) {
// noRedirect: 登录页/未登录时 401 静默失败(保持默认主题),绝不跳转造成循环
Auth.request('GET', '/api/theme', null, function (d, status) {
if (status === 200 && d.effective) apply(d.effective);
if (cb) cb(d);
}, { noRedirect: true });
}
function initTheme() {
fetchTheme();
if (!pollTimer) {
// auto 模式日落/日出切换:每 5 分钟刷新一次
pollTimer = setInterval(fetchTheme, 5 * 60 * 1000);
}
}
global.ThemeBridge = {
apply: apply,
fetch: fetchTheme,
init: initTheme,
getCurrent: function () { return current; }
};
// 页面加载即应用主题
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', initTheme);
} else {
initTheme();
}
})(window);