mirror of
https://github.com/ExamAware/ExamSchedule.git
synced 2025-04-29 19:16:33 +00:00
style: 添加错误提示系统,优化用户体验,处理设置和全屏操作中的异常
This commit is contained in:
parent
689f06977a
commit
61467e3bf4
@ -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();
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
@ -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';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
|
@ -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">
|
||||||
|
Loading…
x
Reference in New Issue
Block a user