112 lines
3.7 KiB
JavaScript
112 lines
3.7 KiB
JavaScript
/*
|
|
* @Author: HenryDu8133 813367384@qq.com
|
|
* @Date: 2026-06-19 17:30:23
|
|
* @LastEditors: HenryDu8133 813367384@qq.com
|
|
* @LastEditTime: 2026-06-19 17:35:05
|
|
* @FilePath: \TicketMachine\web\public-status.js
|
|
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
|
|
*/
|
|
(() => {
|
|
const STATUS_CLASSES = ['is-checking', 'is-online', 'is-offline'];
|
|
const ENDPOINTS = [
|
|
'/api/public/config',
|
|
'/api/public/popular',
|
|
'/api/assets/manifest'
|
|
];
|
|
const ASSISTANT_SCRIPT_ID = 'tm-ai-assistant-script';
|
|
const ASSISTANT_ASSET_VERSION = '2';
|
|
|
|
const roots = () => Array.from(document.querySelectorAll('[data-server-status-root]'));
|
|
|
|
const setStatus = (state, text) => {
|
|
roots().forEach((root) => {
|
|
root.classList.remove(...STATUS_CLASSES);
|
|
root.classList.add(`is-${state}`);
|
|
|
|
const value = root.querySelector('[data-server-status-value]');
|
|
if (value) value.textContent = text;
|
|
});
|
|
};
|
|
|
|
const probe = async () => {
|
|
for (const endpoint of ENDPOINTS) {
|
|
const separator = endpoint.includes('?') ? '&' : '?';
|
|
const controller = new AbortController();
|
|
const timeoutId = window.setTimeout(() => controller.abort(), 3500);
|
|
|
|
try {
|
|
const response = await fetch(`${endpoint}${separator}_=${Date.now()}`, {
|
|
cache: 'no-store',
|
|
signal: controller.signal
|
|
});
|
|
|
|
if (response.ok) {
|
|
window.clearTimeout(timeoutId);
|
|
return true;
|
|
}
|
|
} catch (error) {
|
|
void error;
|
|
}
|
|
|
|
window.clearTimeout(timeoutId);
|
|
}
|
|
|
|
return false;
|
|
};
|
|
|
|
const refresh = async () => {
|
|
if (!roots().length) return;
|
|
|
|
if (navigator.onLine === false) {
|
|
setStatus('offline', '网络离线');
|
|
return;
|
|
}
|
|
|
|
setStatus('checking', '检测中');
|
|
const online = await probe();
|
|
setStatus(online ? 'online' : 'offline', online ? '连接正常' : '连接异常');
|
|
};
|
|
|
|
let timerId = null;
|
|
const isAssistantEligiblePage = (body) => {
|
|
if (!body) return false;
|
|
if (body.classList.contains('jr-admin-page') || body.classList.contains('jr-admin-login-page')) return false;
|
|
return body.classList.contains('jr-public-page')
|
|
|| body.classList.contains('public-search')
|
|
|| body.classList.contains('jr-order-page')
|
|
|| body.classList.contains('jr-ticket-board-page');
|
|
};
|
|
|
|
const loadAssistant = () => {
|
|
const body = document.body;
|
|
if (!isAssistantEligiblePage(body)) return;
|
|
if (document.getElementById(ASSISTANT_SCRIPT_ID) || window.__tmAiAssistantLoaded) return;
|
|
|
|
const script = document.createElement('script');
|
|
script.id = ASSISTANT_SCRIPT_ID;
|
|
script.src = `/ai-assistant.js?v=${ASSISTANT_ASSET_VERSION}`;
|
|
script.defer = true;
|
|
document.head.appendChild(script);
|
|
};
|
|
|
|
const init = () => {
|
|
loadAssistant();
|
|
if (!roots().length || timerId !== null) return;
|
|
|
|
refresh();
|
|
timerId = window.setInterval(refresh, 30000);
|
|
|
|
window.addEventListener('online', refresh);
|
|
window.addEventListener('offline', () => setStatus('offline', '网络离线'));
|
|
document.addEventListener('visibilitychange', () => {
|
|
if (!document.hidden) refresh();
|
|
});
|
|
};
|
|
|
|
if (document.readyState === 'loading') {
|
|
document.addEventListener('DOMContentLoaded', init, { once: true });
|
|
} else {
|
|
init();
|
|
}
|
|
})();
|