app.js 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263
  1. (function () {
  2. function formatDateTime(value) {
  3. if (!value) return '暂无';
  4. const date = new Date(value);
  5. if (Number.isNaN(date.getTime())) return value;
  6. const pad = (number) => String(number).padStart(2, '0');
  7. return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())} ${pad(date.getHours())}:${pad(date.getMinutes())}:${pad(date.getSeconds())}`;
  8. }
  9. function updateMqttStatus(status) {
  10. const root = document.getElementById('mqttStatus');
  11. const text = document.getElementById('mqttStatusText');
  12. if (!root || !text || !status) return;
  13. root.classList.toggle('connected', Boolean(status.connected));
  14. root.classList.toggle('disconnected', !status.connected);
  15. root.title = status.lastError || '';
  16. text.textContent = `MQTT ${status.connected ? '已连接' : (status.message || '未连接')}`;
  17. }
  18. function updateHomeStatus(data) {
  19. const summary = document.getElementById('lightSummary');
  20. if (summary && data.summary) {
  21. summary.textContent = `${data.summary.on} 组开启,${data.summary.off} 组关闭。`;
  22. }
  23. const nextOccurrence = document.getElementById('nextOccurrenceText');
  24. if (nextOccurrence) {
  25. nextOccurrence.textContent = data.nextOccurrence
  26. ? `下一次:${data.nextOccurrence.actionLabel},${data.nextOccurrence.at}。`
  27. : '暂无后续计划。';
  28. }
  29. for (const state of data.states || []) {
  30. const card = document.querySelector(`[data-state-card="${state.channel}"]`);
  31. if (!card) continue;
  32. const value = card.querySelector('[data-state-value]');
  33. const lastSeen = card.querySelector('[data-last-seen]');
  34. if (value) {
  35. value.textContent = state.state;
  36. value.classList.remove('state-on', 'state-off', 'state-unknown');
  37. value.classList.add(`state-${String(state.state).toLowerCase()}`);
  38. }
  39. if (lastSeen) lastSeen.textContent = formatDateTime(state.last_seen_at);
  40. }
  41. }
  42. async function refreshStatus() {
  43. try {
  44. const response = await fetch('/api/status', { cache: 'no-store' });
  45. if (!response.ok) return;
  46. const data = await response.json();
  47. updateMqttStatus(data.mqttStatus);
  48. updateHomeStatus(data);
  49. } catch {
  50. updateMqttStatus({ connected: false, message: '刷新失败' });
  51. }
  52. }
  53. refreshStatus();
  54. setInterval(refreshStatus, 5000);
  55. })();