Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added background_light.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
154 changes: 154 additions & 0 deletions exam/Scripts/examInfo.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
document.addEventListener("DOMContentLoaded", () => {
const examNameElem = document.getElementById("examName");
const messageElem = document.getElementById("message");
const currentTimeElem = document.getElementById("current-time");
const currentSubjectElem = document.getElementById("current-subject");
const examTimingElem = document.getElementById("exam-timing");
const remainingTimeElem = document.getElementById("remaining-time");
const statusElem = document.getElementById("status");
const examTableBodyElem = document.getElementById("exam-table-body");
const roomElem = document.getElementById("room");
let offsetTime = getCookie("offsetTime") || 0;

function fetchData() {
return fetch('exam_config.json', { cache: "no-store" })
.then(response => response.json())
.then(data => {
displayExamInfo(data);
updateCurrentTime();
updateExamInfo(data);
setInterval(() => updateCurrentTime(), 1000);
setInterval(() => updateExamInfo(data), 1000);
})
.catch(error => errorSystem.show('获取考试数据失败: ' + error.message));
}

function displayExamInfo(data) {
try {
const examNameText = data.examName;
const roomText = roomElem.textContent;
examNameElem.innerHTML = `${examNameText} <span id="room">${roomText}</span>`;
messageElem.textContent = data.message;
} catch (e) {
errorSystem.show('显示考试信息失败: ' + e.message);
}
}

function updateCurrentTime() {
try {
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) {
try {
const now = new Date(new Date().getTime() + offsetTime * 1000);
let currentExam = null;
let nextExam = null;
let lastExam = null;

data.examInfos.forEach(exam => {
const start = new Date(exam.start);
const end = new Date(exam.end);
if (now >= start && now <= end) {
currentExam = exam;
}
if (!currentExam && !nextExam && now < start) {
nextExam = exam;
}
if (now > end && (!lastExam || end > new Date(lastExam.end))) {
lastExam = exam;
}
});

if (currentExam) {
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 }))}`;
const remainingTime = (new Date(currentExam.end).getTime() - now.getTime() + 1000) / 1000;
const remainingHours = Math.floor(remainingTime / 3600);
const remainingMinutes = Math.floor((remainingTime % 3600) / 60);
const remainingSeconds = Math.floor(remainingTime % 60);
const remainingTimeText = `${remainingHours}时 ${remainingMinutes}分 ${remainingSeconds}秒`;

if (remainingHours === 0 && remainingMinutes <= 14) {
remainingTimeElem.textContent = `倒计时: ${remainingTimeText}`;
remainingTimeElem.style.color = "red";
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 {
currentSubjectElem.textContent = "考试均已结束";
examTimingElem.textContent = "";
remainingTimeElem.textContent = "";
statusElem.textContent = "状态: 空闲";
statusElem.style.color = "#3946AF";
}

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);
});
} catch (e) {
errorSystem.show('更新考试信息失败: ' + e.message);
}
}

fetchData();
});
17 changes: 17 additions & 0 deletions exam/Scripts/main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
document.addEventListener("DOMContentLoaded", () => {
const fullscreenBtn = document.getElementById("fullscreen-btn");

fullscreenBtn.addEventListener("click", () => {
try {
if (!document.fullscreenElement) {
document.documentElement.requestFullscreen();
} else {
if (document.exitFullscreen) {
document.exitFullscreen();
}
}
} catch (e) {
errorSystem.show('全屏切换失败: ' + e.message);
}
});
});
87 changes: 87 additions & 0 deletions exam/Scripts/settings.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
document.addEventListener("DOMContentLoaded", () => {
const settingsBtn = document.getElementById("settings-btn");
const settingsModal = document.getElementById("settings-modal");
const closeSettingsBtn = document.getElementById("close-settings-btn");
const saveSettingsBtn = document.getElementById("save-settings-btn");
const offsetTimeInput = document.getElementById("offset-time");
const roomInput = document.getElementById("room-input");
const roomElem = document.getElementById("room");
const zoomInput = document.getElementById("zoom-input");
const themeToggle = document.getElementById("theme-toggle");
const themeLink = document.getElementById("theme-link");

let offsetTime = getCookie("offsetTime") || 0;
let room = getCookie("room") || "";
let zoomLevel = getCookie("zoomLevel") || 1;
let theme = getCookie("theme") || "dark";

offsetTime = parseInt(offsetTime);
roomElem.textContent = room;

if (theme === "light") {
themeLink.href = "Styles/light.css";
themeToggle.checked = true;
} else {
themeLink.href = "Styles/dark.css";
themeToggle.checked = false;
}

settingsBtn.addEventListener("click", () => {
try {
offsetTimeInput.value = offsetTime;
roomInput.value = room;
zoomInput.value = zoomLevel;
settingsModal.style.display = "block";
} catch (e) {
errorSystem.show('打开设置失败: ' + e.message);
}
});

closeSettingsBtn.addEventListener("click", () => {
try {
settingsModal.classList.add("fade-out");
setTimeout(() => {
settingsModal.style.display = "none";
settingsModal.classList.remove("fade-out");
}, 300);
} catch (e) {
errorSystem.show('关闭设置失败: ' + e.message);
}
});

saveSettingsBtn.addEventListener("click", () => {
try {
offsetTime = parseInt(offsetTimeInput.value);
room = roomInput.value;
zoomLevel = parseFloat(zoomInput.value);
theme = themeToggle.checked ? "light" : "dark";
setCookie("offsetTime", offsetTime, 365);
setCookie("room", room, 365);
setCookie("zoomLevel", zoomLevel, 365);
setCookie("theme", theme, 365);
roomElem.textContent = room;
document.body.style.zoom = zoomLevel;
themeLink.href = theme === "light" ? "Styles/light.css" : "Styles/dark.css";
settingsModal.classList.add("fade-out");
setTimeout(() => {
settingsModal.style.display = "none";
settingsModal.classList.remove("fade-out");
}, 300);
// 立即生效时间偏移
location.reload();
} catch (e) {
errorSystem.show('保存设置失败: ' + e.message);
}
});

themeToggle.addEventListener("change", () => {
const theme = themeToggle.checked ? "light" : "dark";
themeLink.href = theme === "light" ? "Styles/light.css" : "Styles/dark.css";
});

try {
document.body.style.zoom = zoomLevel;
} catch (e) {
errorSystem.show('初始化缩放失败: ' + e.message);
}
});
39 changes: 39 additions & 0 deletions exam/Scripts/utils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
function setCookie(name, value, days) {
const d = new Date();
d.setTime(d.getTime() + (days * 24 * 60 * 60 * 1000));
const expires = "expires=" + d.toUTCString();
document.cookie = name + "=" + value + ";" + expires + ";path=/";
}

function getCookie(name) {
const nameEQ = name + "=";
const ca = document.cookie.split(';');
for (let i = 0; i < ca.length; i++) {
let c = ca[i];
while (c.charAt(0) === ' ') c = c.substring(1, c.length);
if (c.indexOf(nameEQ) === 0) return c.substring(nameEQ.length, c.length);
}
return null;
}

function formatTimeWithoutSeconds(time) {
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';
}
};
Loading