style: 添加错误提示系统,优化用户体验,处理设置和全屏操作中的异常

This commit is contained in:
MKStoler1024 2025-03-01 23:29:29 +00:00
parent 689f06977a
commit 61467e3bf4
6 changed files with 222 additions and 129 deletions

View File

@ -20,122 +20,134 @@ document.addEventListener("DOMContentLoaded", () => {
setInterval(() => updateCurrentTime(), 1000); setInterval(() => updateCurrentTime(), 1000);
setInterval(() => updateExamInfo(data), 1000); setInterval(() => updateExamInfo(data), 1000);
}) })
.catch(error => console.error('Error fetching exam data:', error)); .catch(error => errorSystem.show('获取考试数据失败: ' + error.message));
} }
function displayExamInfo(data) { function displayExamInfo(data) {
const examNameText = data.examName; try {
const roomText = roomElem.textContent; const examNameText = data.examName;
examNameElem.innerHTML = `${examNameText} <span id="room">${roomText}</span>`; const roomText = roomElem.textContent;
messageElem.textContent = data.message; examNameElem.innerHTML = `${examNameText} <span id="room">${roomText}</span>`;
messageElem.textContent = data.message;
} catch (e) {
errorSystem.show('显示考试信息失败: ' + e.message);
}
} }
function updateCurrentTime() { function updateCurrentTime() {
const now = new Date(new Date().getTime() + offsetTime * 1000); try {
currentTimeElem.textContent = now.toLocaleTimeString('zh-CN', { hour12: false }); const now = new Date(new Date().getTime() + offsetTime * 1000);
currentTimeElem.textContent = now.toLocaleTimeString('zh-CN', { hour12: false });
} catch (e) {
errorSystem.show('更新时间失败: ' + e.message);
}
} }
function updateExamInfo(data) { function updateExamInfo(data) {
const now = new Date(new Date().getTime() + offsetTime * 1000); try {
let currentExam = null; const now = new Date(new Date().getTime() + offsetTime * 1000);
let nextExam = null; let currentExam = null;
let lastExam = null; let nextExam = null;
let lastExam = null;
data.examInfos.forEach(exam => { data.examInfos.forEach(exam => {
const start = new Date(exam.start); const start = new Date(exam.start);
const end = new Date(exam.end); const end = new Date(exam.end);
if (now >= start && now <= end) { if (now >= start && now <= end) {
currentExam = exam; currentExam = exam;
} }
if (!currentExam && !nextExam && now < start) { if (!currentExam && !nextExam && now < start) {
nextExam = exam; nextExam = exam;
} }
if (now > end && (!lastExam || end > new Date(lastExam.end))) { if (now > end && (!lastExam || end > new Date(lastExam.end))) {
lastExam = exam; lastExam = exam;
} }
}); });
if (currentExam) { if (currentExam) {
currentSubjectElem.textContent = `当前科目: ${currentExam.name}`; currentSubjectElem.textContent = `当前科目: ${currentExam.name}`;
examTimingElem.textContent = `起止时间: ${formatTimeWithoutSeconds(new Date(currentExam.start).toLocaleTimeString('zh-CN', { hour12: false }))} - ${formatTimeWithoutSeconds(new Date(currentExam.end).toLocaleTimeString('zh-CN', { hour12: false }))}`; examTimingElem.textContent = `起止时间: ${formatTimeWithoutSeconds(new Date(currentExam.start).toLocaleTimeString('zh-CN', { hour12: false }))} - ${formatTimeWithoutSeconds(new Date(currentExam.end).toLocaleTimeString('zh-CN', { hour12: false }))}`;
const remainingTime = (new Date(currentExam.end).getTime() - now.getTime() + 1000) / 1000; const remainingTime = (new Date(currentExam.end).getTime() - now.getTime() + 1000) / 1000;
const remainingHours = Math.floor(remainingTime / 3600); const remainingHours = Math.floor(remainingTime / 3600);
const remainingMinutes = Math.floor((remainingTime % 3600) / 60); const remainingMinutes = Math.floor((remainingTime % 3600) / 60);
const remainingSeconds = Math.floor(remainingTime % 60); const remainingSeconds = Math.floor(remainingTime % 60);
const remainingTimeText = `${remainingHours}${remainingMinutes}${remainingSeconds}`; const remainingTimeText = `${remainingHours}${remainingMinutes}${remainingSeconds}`;
if (remainingHours === 0 && remainingMinutes <= 14) { if (remainingHours === 0 && remainingMinutes <= 14) {
remainingTimeElem.textContent = `倒计时: ${remainingTimeText}`; remainingTimeElem.textContent = `倒计时: ${remainingTimeText}`;
remainingTimeElem.style.color = "red"; remainingTimeElem.style.color = "red";
remainingTimeElem.style.fontWeight = "bold"; remainingTimeElem.style.fontWeight = "bold";
} else {
remainingTimeElem.textContent = `剩余时间: ${remainingTimeText}`;
remainingTimeElem.style.color = "#93b4f7";
remainingTimeElem.style.fontWeight = "normal";
}
statusElem.textContent = "状态: 进行中";
statusElem.style.color = "#5ba838";
} else if (lastExam && now < new Date(lastExam.end).getTime() + 60000) {
const timeSinceEnd = (now.getTime() - new Date(lastExam.end).getTime()) / 1000;
currentSubjectElem.textContent = `上场科目: ${lastExam.name}`;
examTimingElem.textContent = "";
remainingTimeElem.textContent = ``;
statusElem.textContent = "状态: 已结束";
statusElem.style.color = "red";
} else if (nextExam) {
const timeUntilStart = ((new Date(nextExam.start).getTime() - now.getTime()) / 1000) + 1;
const remainingHours = Math.floor(timeUntilStart / 3600);
const remainingMinutes = Math.floor((timeUntilStart % 3600) / 60);
const remainingSeconds = Math.floor(timeUntilStart % 60);
const remainingTimeText = `${remainingHours}${remainingMinutes}${remainingSeconds}`;
if (timeUntilStart <= 15 * 60) {
currentSubjectElem.textContent = `即将开始: ${nextExam.name}`;
remainingTimeElem.textContent = `倒计时: ${remainingTimeText}`;
remainingTimeElem.style.color = "orange";
remainingTimeElem.style.fontWeight = "bold";
statusElem.textContent = "状态: 即将开始";
statusElem.style.color = "#DBA014";
} else {
currentSubjectElem.textContent = `下一场科目: ${nextExam.name}`;
remainingTimeElem.textContent = "";
statusElem.textContent = "状态: 未开始";
remainingTimeElem.style.fontWeight = "normal";
statusElem.style.color = "#EAEE5B";
}
examTimingElem.textContent = `起止时间: ${formatTimeWithoutSeconds(new Date(nextExam.start).toLocaleTimeString('zh-CN', { hour12: false }))} - ${formatTimeWithoutSeconds(new Date(nextExam.end).toLocaleTimeString('zh-CN', { hour12: false }))}`;
} else { } else {
remainingTimeElem.textContent = `剩余时间: ${remainingTimeText}`; currentSubjectElem.textContent = "考试均已结束";
remainingTimeElem.style.color = "#93b4f7"; examTimingElem.textContent = "";
remainingTimeElem.style.fontWeight = "normal";
}
statusElem.textContent = "状态: 进行中";
statusElem.style.color = "#5ba838";
} else if (lastExam && now < new Date(lastExam.end).getTime() + 60000) {
const timeSinceEnd = (now.getTime() - new Date(lastExam.end).getTime()) / 1000;
currentSubjectElem.textContent = `上场科目: ${lastExam.name}`;
examTimingElem.textContent = "";
remainingTimeElem.textContent = ``;
statusElem.textContent = "状态: 已结束";
statusElem.style.color = "red";
} else if (nextExam) {
const timeUntilStart = ((new Date(nextExam.start).getTime() - now.getTime()) / 1000) + 1;
const remainingHours = Math.floor(timeUntilStart / 3600);
const remainingMinutes = Math.floor((timeUntilStart % 3600) / 60);
const remainingSeconds = Math.floor(timeUntilStart % 60);
const remainingTimeText = `${remainingHours}${remainingMinutes}${remainingSeconds}`;
if (timeUntilStart <= 15 * 60) {
currentSubjectElem.textContent = `即将开始: ${nextExam.name}`;
remainingTimeElem.textContent = `倒计时: ${remainingTimeText}`;
remainingTimeElem.style.color = "orange";
remainingTimeElem.style.fontWeight = "bold";
statusElem.textContent = "状态: 即将开始";
statusElem.style.color = "#DBA014";
} else {
currentSubjectElem.textContent = `下一场科目: ${nextExam.name}`;
remainingTimeElem.textContent = ""; remainingTimeElem.textContent = "";
statusElem.textContent = "状态: 未开始"; statusElem.textContent = "状态: 空闲";
remainingTimeElem.style.fontWeight = "normal"; statusElem.style.color = "#3946AF";
statusElem.style.color = "#EAEE5B";
} }
examTimingElem.textContent = `起止时间: ${formatTimeWithoutSeconds(new Date(nextExam.start).toLocaleTimeString('zh-CN', { hour12: false }))} - ${formatTimeWithoutSeconds(new Date(nextExam.end).toLocaleTimeString('zh-CN', { hour12: false }))}`; examTableBodyElem.innerHTML = "";
} else { data.examInfos.forEach(exam => {
currentSubjectElem.textContent = "考试均已结束"; const start = new Date(exam.start);
examTimingElem.textContent = ""; const end = new Date(exam.end);
remainingTimeElem.textContent = ""; let status = "";
statusElem.textContent = "状态: 空闲"; if (now < start) {
statusElem.style.color = "#3946AF"; status = "即将开始";
} else if (now > end) {
status = "已结束";
} else {
status = "进行中";
}
const row = document.createElement("tr");
row.className = `exam-status-${status}`;
row.innerHTML = `
<td>${exam.name}</td>
<td>${formatTimeWithoutSeconds(new Date(exam.start).toLocaleTimeString('zh-CN', { hour12: false }))}</td>
<td>${formatTimeWithoutSeconds(new Date(exam.end).toLocaleTimeString('zh-CN', { hour12: false }))}</td>
`;
examTableBodyElem.appendChild(row);
});
} catch (e) {
errorSystem.show('更新考试信息失败: ' + e.message);
} }
examTableBodyElem.innerHTML = "";
data.examInfos.forEach(exam => {
const start = new Date(exam.start);
const end = new Date(exam.end);
let status = "";
if (now < start) {
status = "即将开始";
} else if (now > end) {
status = "已结束";
} else {
status = "进行中";
}
const row = document.createElement("tr");
row.className = `exam-status-${status}`;
row.innerHTML = `
<td>${exam.name}</td>
<td>${formatTimeWithoutSeconds(new Date(exam.start).toLocaleTimeString('zh-CN', { hour12: false }))}</td>
<td>${formatTimeWithoutSeconds(new Date(exam.end).toLocaleTimeString('zh-CN', { hour12: false }))}</td>
`;
examTableBodyElem.appendChild(row);
});
} }
fetchData(); fetchData();

View File

@ -2,12 +2,16 @@ document.addEventListener("DOMContentLoaded", () => {
const fullscreenBtn = document.getElementById("fullscreen-btn"); const fullscreenBtn = document.getElementById("fullscreen-btn");
fullscreenBtn.addEventListener("click", () => { fullscreenBtn.addEventListener("click", () => {
if (!document.fullscreenElement) { try {
document.documentElement.requestFullscreen(); if (!document.fullscreenElement) {
} else { document.documentElement.requestFullscreen();
if (document.exitFullscreen) { } else {
document.exitFullscreen(); if (document.exitFullscreen) {
document.exitFullscreen();
}
} }
} catch (e) {
errorSystem.show('全屏切换失败: ' + e.message);
} }
}); });
}); });

View File

@ -16,37 +16,53 @@ document.addEventListener("DOMContentLoaded", () => {
roomElem.textContent = room; roomElem.textContent = room;
settingsBtn.addEventListener("click", () => { settingsBtn.addEventListener("click", () => {
offsetTimeInput.value = offsetTime; try {
roomInput.value = room; offsetTimeInput.value = offsetTime;
zoomInput.value = zoomLevel; roomInput.value = room;
settingsModal.style.display = "block"; zoomInput.value = zoomLevel;
settingsModal.style.display = "block";
} catch (e) {
errorSystem.show('打开设置失败: ' + e.message);
}
}); });
closeSettingsBtn.addEventListener("click", () => { closeSettingsBtn.addEventListener("click", () => {
settingsModal.classList.add("fade-out"); try {
setTimeout(() => { settingsModal.classList.add("fade-out");
settingsModal.style.display = "none"; setTimeout(() => {
settingsModal.classList.remove("fade-out"); settingsModal.style.display = "none";
}, 300); settingsModal.classList.remove("fade-out");
}, 300);
} catch (e) {
errorSystem.show('关闭设置失败: ' + e.message);
}
}); });
saveSettingsBtn.addEventListener("click", () => { saveSettingsBtn.addEventListener("click", () => {
offsetTime = parseInt(offsetTimeInput.value); try {
room = roomInput.value; offsetTime = parseInt(offsetTimeInput.value);
zoomLevel = parseFloat(zoomInput.value); room = roomInput.value;
setCookie("offsetTime", offsetTime, 365); zoomLevel = parseFloat(zoomInput.value);
setCookie("room", room, 365); setCookie("offsetTime", offsetTime, 365);
setCookie("zoomLevel", zoomLevel, 365); setCookie("room", room, 365);
roomElem.textContent = room; setCookie("zoomLevel", zoomLevel, 365);
document.body.style.zoom = zoomLevel; roomElem.textContent = room;
settingsModal.classList.add("fade-out"); document.body.style.zoom = zoomLevel;
setTimeout(() => { settingsModal.classList.add("fade-out");
settingsModal.style.display = "none"; setTimeout(() => {
settingsModal.classList.remove("fade-out"); settingsModal.style.display = "none";
}, 300); settingsModal.classList.remove("fade-out");
// 立即生效时间偏移 }, 300);
location.reload(); // 立即生效时间偏移
location.reload();
} catch (e) {
errorSystem.show('保存设置失败: ' + e.message);
}
}); });
document.body.style.zoom = zoomLevel; try {
document.body.style.zoom = zoomLevel;
} catch (e) {
errorSystem.show('初始化缩放失败: ' + e.message);
}
}); });

View File

@ -19,3 +19,21 @@ function getCookie(name) {
function formatTimeWithoutSeconds(time) { function formatTimeWithoutSeconds(time) {
return time.slice(0, -3); return time.slice(0, -3);
} }
const errorSystem = {
show: function(message) {
try {
const container = document.querySelector('.error-container');
const content = document.getElementById('errorMessage');
content.textContent = message;
container.style.display = 'flex';
setTimeout(this.hide, 5000);
} catch(e) {
console.error('错误提示系统异常:', e);
}
},
hide: function() {
const container = document.querySelector('.error-container');
if (container) container.style.display = 'none';
}
};

View File

@ -290,3 +290,43 @@ td:last-child {
#close-settings-btn:hover { #close-settings-btn:hover {
background-color: #c9302c; background-color: #c9302c;
} }
.error-container {
position: fixed;
bottom: 0;
left: 0;
right: 0;
background: #ff6b6b;
color: white;
padding: 16px;
display: none;
z-index: 10001;
animation: slideUp 0.3s ease;
}
@keyframes slideUp {
from { transform: translateY(100%); }
to { transform: translateY(0); }
}
.error-content {
max-width: 800px;
margin: 0 auto;
font-size: 15px;
display: flex;
align-items: center;
gap: 12px;
}
.error-content:before {
content: '!';
display: flex;
align-items: center;
justify-content: center;
width: 24px;
height: 24px;
background: white;
color: #ff6b6b;
border-radius: 50%;
font-weight: bold;
}

View File

@ -8,6 +8,9 @@
<link href="https://fonts.googleapis.com/css?family=Roboto:300,400,500&display=swap" rel="stylesheet"> <link href="https://fonts.googleapis.com/css?family=Roboto:300,400,500&display=swap" rel="stylesheet">
</head> </head>
<body> <body>
<div class="error-container">
<div class="error-content" id="errorMessage"></div>
</div>
<button id="settings-btn">设置</button> <button id="settings-btn">设置</button>
<button id="fullscreen-btn">全屏</button> <button id="fullscreen-btn">全屏</button>
<div class="container"> <div class="container">