feat(theme): 砂狼白子主题 —— 真实立绘/头像 + 自绘装饰
素材(第三方,仅个人自用): - 立绘/头像来自 SchaleDB(schaledb.com),学生 Id 10010 = 砂狼白子 - 版权归 NEXON Games / Yostar(蔚蓝档案),来源与公开部署提示见 README「主题」章节 自绘装饰(SVG/CSS,按公开设定还原): - 天蓝围巾飘带(顶栏底边)、公路车(左下角 + 加载车轮) - 光环水印:倾斜椭圆环 + 四方位带圆头短杆(对齐官方造型,此前误画为正圆+三角) - 倒十字发饰分组标识、迷你光环状态点 其他:主题切换(settings.theme / ?theme= / 顶栏按钮)、立绘位 settings.artwork 修复:dataFilter=uptimerobot 时平均延迟恒为「–」(改为纯外部来源时以其为唯一口径)
This commit is contained in:
+56
-4
@@ -1,4 +1,4 @@
|
||||
const VERSION = '0.6.0';
|
||||
const VERSION = '0.7.0';
|
||||
const HB_LIMIT = 48;
|
||||
const UPTIME_DAYS = 90;
|
||||
const BROWSER_CONCURRENCY = 6;
|
||||
@@ -15,6 +15,7 @@ const state = {
|
||||
source: null,
|
||||
filter: 'all',
|
||||
view: 'cards',
|
||||
theme: 'default',
|
||||
refreshTimer: null,
|
||||
nextRefreshAt: 0,
|
||||
loading: false,
|
||||
@@ -537,6 +538,8 @@ function localStats() {
|
||||
let latCount = 0;
|
||||
let uptimeUp = 0;
|
||||
let uptimeTotal = 0;
|
||||
// 与探针口径一致:混合来源时平均延迟只统计自建探测;若展示集合只有外部数据源,则以其延迟为唯一口径
|
||||
const hasProbe = monitors.some((m) => !isExternal(m));
|
||||
for (const m of monitors) {
|
||||
const st = state.status?.monitors?.[m.id];
|
||||
if (!st || st.status === 'pending') {
|
||||
@@ -545,8 +548,7 @@ function localStats() {
|
||||
}
|
||||
if (st.status === 'up') up++;
|
||||
else down++;
|
||||
// 与探针口径一致:平均延迟只统计自建探测目标
|
||||
if (!isExternal(m) && st.latency != null) {
|
||||
if (st.latency != null && (!isExternal(m) || !hasProbe)) {
|
||||
latSum += st.latency;
|
||||
latCount++;
|
||||
}
|
||||
@@ -666,7 +668,10 @@ function setLoading(on, text = '刷新中…') {
|
||||
state.loading = on;
|
||||
const btn = $('refresh-btn');
|
||||
btn.disabled = on;
|
||||
btn.textContent = on ? text : '刷新';
|
||||
// 车轮图标(砂狼白子骑行意象,主题里会转起来)
|
||||
btn.innerHTML = on
|
||||
? `<svg class="wheel" viewBox="0 0 24 24" aria-hidden="true"><circle cx="12" cy="12" r="10" fill="none" stroke="currentColor" stroke-width="2" opacity="0.35"/><g stroke="currentColor" stroke-width="1.3"><line x1="12" y1="2" x2="12" y2="22"/><line x1="2" y1="12" x2="22" y2="12"/><line x1="4.9" y1="4.9" x2="19.1" y2="19.1"/><line x1="19.1" y1="4.9" x2="4.9" y2="19.1"/></g><circle cx="12" cy="12" r="2.2" fill="currentColor"/></svg><span>${escapeHtml(text)}</span>`
|
||||
: '刷新';
|
||||
}
|
||||
|
||||
async function refresh({ force = false } = {}) {
|
||||
@@ -748,9 +753,55 @@ function startAutoRefresh() {
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
/* ---------- 主题 ---------- */
|
||||
|
||||
const THEMES = { default: '默认', shiroko: '砂狼白子' };
|
||||
|
||||
function resolveTheme() {
|
||||
const q = new URLSearchParams(location.search).get('theme');
|
||||
let saved = null;
|
||||
try {
|
||||
saved = localStorage.getItem('shiroko.theme');
|
||||
} catch { /* 隐私模式 */ }
|
||||
return [q, saved, state.config?.settings?.theme].find((t) => t && THEMES[t]) ?? 'default';
|
||||
}
|
||||
|
||||
// 角色立绘位:主题为白子且配置了 artwork 时才插入;文件不存在则静默移除(不留破图)
|
||||
function applyArtwork() {
|
||||
document.querySelector('.artwork')?.remove();
|
||||
const src = state.config?.settings?.artwork;
|
||||
if (state.theme !== 'shiroko' || !src) return;
|
||||
const img = document.createElement('img');
|
||||
img.className = 'artwork';
|
||||
img.alt = '';
|
||||
img.src = src;
|
||||
img.addEventListener('error', () => img.remove());
|
||||
document.body.appendChild(img);
|
||||
}
|
||||
|
||||
function applyTheme(theme, { persist = true } = {}) {
|
||||
state.theme = THEMES[theme] ? theme : 'default';
|
||||
if (state.theme === 'default') delete document.body.dataset.theme;
|
||||
else document.body.dataset.theme = state.theme;
|
||||
if (persist) {
|
||||
try {
|
||||
localStorage.setItem('shiroko.theme', state.theme);
|
||||
} catch { /* 忽略 */ }
|
||||
}
|
||||
const icon = document.querySelector('link[rel="icon"]');
|
||||
if (icon) icon.setAttribute('href', state.theme === 'shiroko' ? 'assets/favicon-shiroko.png' : 'assets/favicon.svg');
|
||||
applyArtwork();
|
||||
const btn = $('theme-btn');
|
||||
if (btn) {
|
||||
btn.classList.toggle('active', state.theme === 'shiroko');
|
||||
btn.title = state.theme === 'shiroko' ? '当前主题:砂狼白子(点击切回默认)' : '当前主题:默认(点击切换到砂狼白子主题)';
|
||||
}
|
||||
}
|
||||
|
||||
function bindEvents() {
|
||||
// 只有手动点「刷新」才会触发一次重新检测;自动刷新是只读的
|
||||
$('refresh-btn').addEventListener('click', () => refresh({ force: true }));
|
||||
$('theme-btn')?.addEventListener('click', () => applyTheme(state.theme === 'shiroko' ? 'default' : 'shiroko'));
|
||||
}
|
||||
|
||||
/* ---------- 启动 ---------- */
|
||||
@@ -767,6 +818,7 @@ async function init() {
|
||||
$('site-desc').textContent = state.config.settings?.description || '';
|
||||
const versionEl = document.querySelector('.version');
|
||||
if (versionEl) versionEl.textContent = `shiroko-monitor v${VERSION}`;
|
||||
applyTheme(resolveTheme());
|
||||
await resolveSource();
|
||||
state.view = resolveView();
|
||||
bindEvents();
|
||||
|
||||
Reference in New Issue
Block a user