diff --git a/ExamCloudSchedule/index.html b/ExamCloudSchedule/index.html
new file mode 100644
index 0000000..f2d8014
--- /dev/null
+++ b/ExamCloudSchedule/index.html
@@ -0,0 +1,58 @@
+
+
+
+
+
+ Exam Schedule
+
+
+
+
+
+
+
+
+ 考试安排
+
+
+
+
+
+
+
+
+
+ 科目 |
+ 开始时间 |
+ 结束时间 |
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ExamCloudSchedule/script.js b/ExamCloudSchedule/script.js
new file mode 100644
index 0000000..527351c
--- /dev/null
+++ b/ExamCloudSchedule/script.js
@@ -0,0 +1,230 @@
+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 fullscreenBtn = document.getElementById("fullscreen-btn");
+ 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");
+
+ let offsetTime = getCookie("offsetTime") || 0;
+ let room = getCookie("room") || "";
+ let zoomLevel = getCookie("zoomLevel") || 1;
+
+ offsetTime = parseInt(offsetTime);
+ roomElem.textContent = room;
+
+ function fetchData() {
+ const urlParams = new URLSearchParams(window.location.search);
+ const configId = urlParams.get('configId');
+ if (!configId) {
+ console.error('No configId provided');
+ return;
+ }
+
+ return fetch(`/get_config.php?id=${encodeURIComponent(configId)}`, { cache: "no-store" }) // 不保留缓存
+ .then(response => response.json())
+ .then(data => {
+ displayExamInfo(data);
+ updateCurrentTime();
+ updateExamInfo(data);
+ setInterval(() => updateCurrentTime(), 1000); // Update current time every second
+ setInterval(() => updateExamInfo(data), 1000); // Update exam info every second
+ })
+ .catch(error => console.error('Error fetching exam data:', error));
+ }
+
+ function displayExamInfo(data) {
+ // Display exam name
+ const examNameText = data.examName;
+ const roomText = roomElem.textContent;
+ examNameElem.innerHTML = `${examNameText} ${roomText}`;
+ // Display message
+ messageElem.textContent = data.message;
+ }
+
+ function updateCurrentTime() {
+ const now = new Date(new Date().getTime() + offsetTime * 1000);
+ currentTimeElem.textContent = now.toLocaleTimeString('zh-CN', { hour12: false });
+ }
+
+ function formatTimeWithoutSeconds(time) {
+ // Convert time to string and remove seconds if present
+ return time.slice(0, -3);
+ }
+
+ function updateExamInfo(data) {
+ 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";
+ }
+
+ // Update next exams table
+ 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 = `
+ ${exam.name} |
+ ${formatTimeWithoutSeconds(new Date(exam.start).toLocaleTimeString('zh-CN', { hour12: false }))} |
+ ${formatTimeWithoutSeconds(new Date(exam.end).toLocaleTimeString('zh-CN', { hour12: false }))} |
+ `;
+ examTableBodyElem.appendChild(row);
+ });
+ }
+
+ // Fullscreen functionality
+ fullscreenBtn.addEventListener("click", () => {
+ if (!document.fullscreenElement) {
+ document.documentElement.requestFullscreen();
+ } else {
+ if (document.exitFullscreen) {
+ document.exitFullscreen();
+ }
+ }
+ });
+
+ // Open settings modal
+ settingsBtn.addEventListener("click", () => {
+ offsetTimeInput.value = offsetTime;
+ roomInput.value = room;
+ zoomInput.value = zoomLevel;
+ settingsModal.style.display = "block";
+ });
+
+ // Close settings modal
+ closeSettingsBtn.addEventListener("click", () => {
+ settingsModal.style.display = "none";
+ });
+
+ // Save settings
+ saveSettingsBtn.addEventListener("click", () => {
+ offsetTime = parseInt(offsetTimeInput.value);
+ room = roomInput.value;
+ zoomLevel = parseFloat(zoomInput.value);
+ setCookie("offsetTime", offsetTime, 365);
+ setCookie("room", room, 365);
+ setCookie("zoomLevel", zoomLevel, 365);
+ roomElem.textContent = room;
+ document.body.style.zoom = zoomLevel;
+ settingsModal.style.display = "none";
+ });
+
+ document.body.style.zoom = zoomLevel;
+
+ // Utility function to set a cookie
+ 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=/";
+ }
+
+ // Utility function to get a cookie
+ 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;
+ }
+
+ fetchData();
+});
diff --git a/ExamCloudSchedule/styles.css b/ExamCloudSchedule/styles.css
new file mode 100644
index 0000000..57f31a4
--- /dev/null
+++ b/ExamCloudSchedule/styles.css
@@ -0,0 +1,260 @@
+body {
+ font-family: 'HarmonyOS Sans SC Regular', 'Roboto', Arial, sans-serif;
+ margin: 0;
+ padding: 0;
+ background: url('../background.jpg') no-repeat center center fixed;
+ background-size: cover;
+ animation: fadeIn 1s;
+ color: #e0e0e0;
+ overflow: auto; /* 允许页面滚动 */
+}
+
+/* 隐藏滚动条 */
+body::-webkit-scrollbar {
+ display: none;
+}
+
+@keyframes fadeIn {
+ from { opacity: 0; }
+ to { opacity: 1; }
+}
+
+#fullscreen-btn {
+ position: absolute;
+ top: 20px;
+ right: 20px;
+ padding: 10px 20px;
+ font-size: 1rem;
+ cursor: pointer;
+ background-color: #1f1f1f;
+ color: #e0e0e0;
+ border: 1px solid #333;
+ border-radius: 5px;
+ box-shadow: 0 0 10px rgba(0, 0, 0, 0.2);
+ transition: background-color 0.3s ease, transform 0.3s ease;
+ z-index: 1001;
+}
+
+#settings-btn {
+ position: absolute;
+ top: 20px;
+ right: 120px; /* Fullscreen button's left */
+ padding: 10px 20px;
+ font-size: 1rem;
+ cursor: pointer;
+ background-color: #1f1f1f;
+ color: #e0e0e0;
+ border: 1px solid #333;
+ border-radius: 5px;
+ box-shadow: 0 0 10px rgba(0, 0, 0, 0.2);
+ transition: background-color 0.3s ease, transform 0.3s ease;
+ z-index: 1001;
+}
+
+#settings-btn:hover {
+ background-color: #333;
+ transform: scale(1.05);
+}
+
+#fullscreen-btn:hover {
+ background-color: #333;
+ transform: scale(1.05);
+}
+
+.container {
+ padding: 20px;
+ max-width: 1400px; /* 增加主体部分宽度 */
+ margin: auto;
+ background-color: rgba(31, 31, 31, 0.5); /* 使用rgba设置背景透明度 */
+ border-radius: 8px;
+ box-shadow: 0 0 20px rgba(0, 0, 0, 0.3);
+}
+
+h1 {
+ font-size: 3.5rem;
+ font-weight: bold;
+ text-align: left;
+ margin-bottom: 10px;
+ color: #e0e0e0;
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+}
+
+#room {
+ font-size: 3.5rem;
+ font-weight: bold;
+ color: #e0e0e0;
+ position: relative;
+ right: 0;
+ margin-left: 20px; /* 调整位置使其保持在container中 */
+}
+
+#message {
+ font-size: 1.5rem;
+ color: #16a3d1;
+ margin-bottom: 20px;
+}
+
+.content {
+ display: flex;
+ justify-content: space-between;
+}
+
+.left-column, .right-column {
+ width: 48%;
+ background-color: rgba(31, 31, 31, 0.2);
+ padding: 20px;
+ box-shadow: 0 0 10px rgba(0, 0, 0, 0.3);
+ border-radius: 8px;
+}
+
+#current-time {
+ font-size: 10rem;
+ font-weight: bold;
+ text-align: center;
+ margin-bottom: 20px;
+ color: #7cc3fb;
+}
+
+#current-subject, #exam-timing, #remaining-time, #status {
+ font-size: 3rem;
+ margin: 10px 0;
+ text-align: left;
+ color: #e0e0e0;
+}
+
+table {
+ width: 100%;
+ border-collapse: collapse;
+ margin-top: 20px;
+ border: 1px solid #333;
+ background-color: rgba(31, 31, 31, 0.5);
+}
+
+th, td {
+ border: 1px solid #333;
+ padding: 8px; /* 缩短行高 */
+ font-size: 2rem;
+ text-align: center;
+}
+
+th {
+ background-color: #333;
+ color: #7cc3fb;
+ font-weight: bold;
+ border-bottom: 2px solid #2b71ad;
+}
+
+.exam-status-进行中 td {
+ color: #5ba838 !important; /* 绿色字体 */
+}
+
+.exam-status-即将开始 td {
+ color: #fe9901 !important; /* 橙色字体 */
+}
+
+.exam-status-已结束 td {
+ color: #ec0434 !important; /* 红色字体 */
+}
+
+.exam-status-空闲 td {
+ color: blue !important; /* 蓝色字体 */
+}
+
+tr:hover {
+ background-color: #333;
+}
+
+table {
+ border-radius: 8px;
+ overflow: hidden;
+}
+
+td {
+ border-bottom: 1px solid #333;
+}
+
+td:first-child {
+ border-top-left-radius: 8px;
+ border-bottom-left-radius: 8px;
+}
+
+td:last-child {
+ border-top-right-radius: 8px;
+ border-bottom-right-radius: 8px;
+}
+
+#settings-modal {
+ display: none;
+ position: fixed;
+ z-index: 1000;
+ left: 0;
+ top: 0;
+ width: 100%;
+ height: 100%;
+ overflow: auto;
+ background-color: rgb(0, 0, 0);
+ background-color: rgba(0, 0, 0, 0.4);
+ padding-top: 60px;
+}
+
+#settings-modal-content {
+ background-color: #1f1f1f;
+ margin: 5% auto;
+ padding: 20px;
+ border: 1px solid #888;
+ width: 80%;
+ max-width: 600px;
+ border-radius: 10px;
+}
+
+#settings-modal-content label {
+ font-size: 2rem;
+}
+
+#settings-modal-content input[type="number"],
+#settings-modal-content input[type="text"] {
+ font-size: 2rem;
+ padding: 10px;
+ margin-top: 10px;
+ margin-bottom: 20px;
+ width: 100%;
+ box-sizing: border-box;
+ border: 1px solid #ccc;
+ border-radius: 5px;
+ background-color: #121212;
+ color: #e0e0e0;
+}
+
+#settings-modal-content button {
+ padding: 10px 20px;
+ font-size: 2rem;
+ cursor: pointer;
+ background-color: #93b4f7;
+ color: white;
+ border: none;
+ border-radius: 5px;
+ box-shadow: 0 0 10px rgba(0, 0, 0, 0.2);
+ transition: background-color 0.3s ease;
+}
+
+#settings-modal-content button:hover {
+ background-color: #45a049;
+}
+
+#close-settings-btn {
+ padding: 10px 20px;
+ font-size: 2rem;
+ cursor: pointer;
+ background-color: #d9534f;
+ color: white;
+ border: none;
+ border-radius: 5px;
+ box-shadow: 0 0 10px rgba(0, 0, 0, 0.2);
+ transition: background-color 0.3s ease;
+}
+
+#close-settings-btn:hover {
+ background-color: #c9302c;
+}
diff --git a/background.jpg b/background.jpg
new file mode 100644
index 0000000..3da109e
Binary files /dev/null and b/background.jpg differ
diff --git a/favicon.ico b/favicon.ico
new file mode 100644
index 0000000..596edad
Binary files /dev/null and b/favicon.ico differ
diff --git a/index.php b/index.php
index a7d26e3..7bb135e 100644
--- a/index.php
+++ b/index.php
@@ -74,6 +74,7 @@ header('Content-Type: text/html; charset=utf-8');
+
@@ -86,10 +87,12 @@ header('Content-Type: text/html; charset=utf-8');
function loadConfig() {
const configId = document.getElementById('configId').value.trim();
const resultDiv = document.getElementById('result');
+ const enterButton = document.getElementById('enterButton');
resultDiv.innerHTML = '加载中...';
if(!configId) {
resultDiv.innerHTML = '请输入配置ID';
+ enterButton.style.display = 'none';
return;
}
@@ -102,12 +105,19 @@ header('Content-Type: text/html; charset=utf-8');
})
.then(data => {
resultDiv.innerHTML = `${syntaxHighlight(JSON.stringify(data, null, 4))}
`;
+ enterButton.style.display = 'inline-block';
})
.catch(error => {
resultDiv.innerHTML = `错误:${error.error || '获取配置失败'}`;
+ enterButton.style.display = 'none';
});
}
+ function enterSchedule() {
+ const configId = document.getElementById('configId').value.trim();
+ window.location.href = `/ExamCloudSchedule/index.html?configId=${encodeURIComponent(configId)}`;
+ }
+
// JSON高亮显示
function syntaxHighlight(json) {
json = json.replace(/&/g, '&').replace(//g, '>');