From 6432f2da7c73480719bae54e6ef0715330128968 Mon Sep 17 00:00:00 2001
From: MKStoler1024 <158786854+MKStoler1024@users.noreply.github.com>
Date: Sat, 26 Apr 2025 17:54:53 +0000
Subject: [PATCH] =?UTF-8?q?feat:=20=E5=90=88=E5=B9=B6=E7=9C=8B=E6=9D=BF?=
=?UTF-8?q?=E5=92=8C=E5=B9=BF=E6=92=AD?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.devcontainer/devcontainer.json | 27 +
.github/dependabot.yml | 12 +
.../Scripts}/audioController.js | 1 +
exam/Scripts/examInfo.js | 2 +
exam/Scripts/reminderModal.js | 26 +
.../scripts => exam/Scripts}/reminderQueue.js | 1 +
exam/Scripts/reminderSettings.js | 155 ++++++
exam/Scripts/utils.js | 2 +
exam/Styles/ealg/dark.css | 450 ++++++++++++++--
exam/Styles/ealg/light.css | 262 +++++++++-
{notification => exam}/audio/15min_left.mp3 | Bin
{notification => exam}/audio/30min_left.mp3 | Bin
{notification => exam}/audio/classstart.mp3 | Bin
{notification => exam}/audio/end.mp3 | Bin
{notification => exam}/audio/hedui_eng.mp3 | Bin
{notification => exam}/audio/hedui_noeng.mp3 | Bin
{notification => exam}/audio/jinchang.mp3 | Bin
{notification => exam}/audio/start.mp3 | Bin
.../audio/zhanshikemudai.mp3 | Bin
{notification => exam}/audio_files.json | 0
exam/exam_config.json | 2 +-
exam/index.html | 33 +-
index.html | 22 +-
notification/course_schedule.json | 47 --
notification/index.html | 90 ----
notification/scripts/config.js | 138 -----
notification/scripts/courseSchedule.js | 172 -------
notification/scripts/display.js | 56 --
notification/scripts/errorSystem.js | 17 -
notification/scripts/script.js | 210 --------
notification/scripts/settings.js | 149 ------
notification/scripts/utils.js | 48 --
notification/styles/action-btn.css | 20 -
notification/styles/base.css | 12 -
notification/styles/control-btn.css | 24 -
notification/styles/dark-mode.css | 138 -----
notification/styles/file-input-label.css | 15 -
notification/styles/fullscreen-mode.css | 40 --
notification/styles/info-error.css | 69 ---
notification/styles/reminder-table.css | 55 --
notification/styles/schedule-table.css | 42 --
notification/styles/settings-panel.css | 60 ---
notification/styles/status-box.css | 24 -
notification/styles/style.css | 479 ------------------
notification/styles/switch.css | 44 --
45 files changed, 923 insertions(+), 2021 deletions(-)
create mode 100644 .devcontainer/devcontainer.json
create mode 100644 .github/dependabot.yml
rename {notification/scripts => exam/Scripts}/audioController.js (98%)
create mode 100644 exam/Scripts/reminderModal.js
rename {notification/scripts => exam/Scripts}/reminderQueue.js (94%)
create mode 100644 exam/Scripts/reminderSettings.js
rename {notification => exam}/audio/15min_left.mp3 (100%)
rename {notification => exam}/audio/30min_left.mp3 (100%)
rename {notification => exam}/audio/classstart.mp3 (100%)
rename {notification => exam}/audio/end.mp3 (100%)
rename {notification => exam}/audio/hedui_eng.mp3 (100%)
rename {notification => exam}/audio/hedui_noeng.mp3 (100%)
rename {notification => exam}/audio/jinchang.mp3 (100%)
rename {notification => exam}/audio/start.mp3 (100%)
rename {notification => exam}/audio/zhanshikemudai.mp3 (100%)
rename {notification => exam}/audio_files.json (100%)
delete mode 100644 notification/course_schedule.json
delete mode 100644 notification/index.html
delete mode 100644 notification/scripts/config.js
delete mode 100644 notification/scripts/courseSchedule.js
delete mode 100644 notification/scripts/display.js
delete mode 100644 notification/scripts/errorSystem.js
delete mode 100644 notification/scripts/script.js
delete mode 100644 notification/scripts/settings.js
delete mode 100644 notification/scripts/utils.js
delete mode 100644 notification/styles/action-btn.css
delete mode 100644 notification/styles/base.css
delete mode 100644 notification/styles/control-btn.css
delete mode 100644 notification/styles/dark-mode.css
delete mode 100644 notification/styles/file-input-label.css
delete mode 100644 notification/styles/fullscreen-mode.css
delete mode 100644 notification/styles/info-error.css
delete mode 100644 notification/styles/reminder-table.css
delete mode 100644 notification/styles/schedule-table.css
delete mode 100644 notification/styles/settings-panel.css
delete mode 100644 notification/styles/status-box.css
delete mode 100644 notification/styles/style.css
delete mode 100644 notification/styles/switch.css
diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json
new file mode 100644
index 0000000..53cbd50
--- /dev/null
+++ b/.devcontainer/devcontainer.json
@@ -0,0 +1,27 @@
+// For format details, see https://aka.ms/devcontainer.json. For config options, see the
+// README at: https://github.com/devcontainers/templates/tree/main/src/php
+{
+ "name": "PHP",
+ // Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile
+ "image": "mcr.microsoft.com/devcontainers/php:1-8.2-bullseye",
+ // Configure tool-specific properties.
+ "customizations": {
+ // Configure properties specific to VS Code.
+ "vscode": {
+ "extensions": [
+ "ikappas.composer"
+ ]
+ }
+ },
+ // Use 'forwardPorts' to make a list of ports inside the container available locally.
+ "forwardPorts": [
+ 8080
+ ],
+ "features": {
+ "ghcr.io/devcontainers/features/github-cli:1": {}
+ },
+ // Use 'postCreateCommand' to run commands after the container is created.
+ "postCreateCommand": "sudo chmod a+x \"$(pwd)\" && sudo rm -rf /var/www/html && sudo ln -s \"$(pwd)\" /var/www/html; if [ -f composer.json ];then composer install;fi"
+ // Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root.
+ // "remoteUser": "root"
+}
\ No newline at end of file
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
new file mode 100644
index 0000000..f33a02c
--- /dev/null
+++ b/.github/dependabot.yml
@@ -0,0 +1,12 @@
+# To get started with Dependabot version updates, you'll need to specify which
+# package ecosystems to update and where the package manifests are located.
+# Please see the documentation for more information:
+# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
+# https://containers.dev/guide/dependabot
+
+version: 2
+updates:
+ - package-ecosystem: "devcontainers"
+ directory: "/"
+ schedule:
+ interval: weekly
diff --git a/notification/scripts/audioController.js b/exam/Scripts/audioController.js
similarity index 98%
rename from notification/scripts/audioController.js
rename to exam/Scripts/audioController.js
index c2fd514..2b24de8 100644
--- a/notification/scripts/audioController.js
+++ b/exam/Scripts/audioController.js
@@ -1,3 +1,4 @@
+// ...复制 notification/scripts/audioController.js 的全部内容...
var audioController = (function() {
var audioPool = [];
var maxPoolSize = 3;
diff --git a/exam/Scripts/examInfo.js b/exam/Scripts/examInfo.js
index 0cc15ee..c9d7c8f 100644
--- a/exam/Scripts/examInfo.js
+++ b/exam/Scripts/examInfo.js
@@ -42,6 +42,7 @@ document.addEventListener("DOMContentLoaded", () => {
if (localConfig) {
try {
const data = JSON.parse(localConfig);
+ window.examConfigData = data; // 暴露全局变量供提醒队列使用
displayExamInfo(data);
updateCurrentTime();
updateExamInfo(data);
@@ -58,6 +59,7 @@ document.addEventListener("DOMContentLoaded", () => {
return fetch('exam_config.json', { cache: "no-store" })
.then(response => response.json())
.then(data => {
+ window.examConfigData = data; // 暴露全局变量供提醒队列使用
displayExamInfo(data);
updateCurrentTime();
updateExamInfo(data);
diff --git a/exam/Scripts/reminderModal.js b/exam/Scripts/reminderModal.js
new file mode 100644
index 0000000..8a56674
--- /dev/null
+++ b/exam/Scripts/reminderModal.js
@@ -0,0 +1,26 @@
+document.addEventListener("DOMContentLoaded", function() {
+ const reminderBtn = document.getElementById("reminder-settings-btn");
+ const reminderModal = document.getElementById("reminder-modal");
+ const closeReminderBtn = document.getElementById("close-reminder-btn");
+ const saveReminderBtn = document.getElementById("save-reminder-btn");
+
+ reminderBtn.addEventListener("click", function() {
+ reminderModal.style.display = "block";
+ });
+
+ closeReminderBtn.addEventListener("click", function() {
+ reminderModal.style.display = "none";
+ });
+
+ saveReminderBtn.addEventListener("click", function() {
+ saveConfig();
+ reminderModal.style.display = "none";
+ });
+
+ // 点击弹窗外部关闭
+ window.addEventListener("click", function(event) {
+ if (event.target === reminderModal) {
+ reminderModal.style.display = "none";
+ }
+ });
+});
diff --git a/notification/scripts/reminderQueue.js b/exam/Scripts/reminderQueue.js
similarity index 94%
rename from notification/scripts/reminderQueue.js
rename to exam/Scripts/reminderQueue.js
index 3e07e74..b53df31 100644
--- a/notification/scripts/reminderQueue.js
+++ b/exam/Scripts/reminderQueue.js
@@ -1,3 +1,4 @@
+// ...复制 notification/scripts/reminderQueue.js 的全部内容...
var reminderQueue = (function() {
var queue = [];
var audioCache = {};
diff --git a/exam/Scripts/reminderSettings.js b/exam/Scripts/reminderSettings.js
new file mode 100644
index 0000000..e8dcbbd
--- /dev/null
+++ b/exam/Scripts/reminderSettings.js
@@ -0,0 +1,155 @@
+// 提醒设置相关函数,适配exam页面
+
+function addReminder() {
+ var table = document.getElementById('reminderTable');
+ var row = table.insertRow(table.rows.length - 1);
+ row.innerHTML = `
+
+
+ |
+ |
+
+
+ |
+ |
+ `;
+ row.cells[0].querySelector('select').addEventListener('change', function() {
+ row.cells[1].querySelector('input').disabled = this.value === 'start' || this.value === 'end';
+ row.cells[1].querySelector('input').placeholder = this.value === 'start' || this.value === 'end' ? '-' : '分钟';
+ });
+ audioController.populateAudioSelect();
+}
+
+function removeReminder(button) {
+ var row = button.parentNode.parentNode;
+ row.parentNode.removeChild(row);
+}
+
+function saveConfig() {
+ try {
+ var table = document.getElementById('reminderTable');
+ var reminders = [];
+ for (var i = 1; i < table.rows.length - 1; i++) {
+ var row = table.rows[i];
+ var condition = row.cells[0].querySelector('select').value;
+ var timeInput = row.cells[1].querySelector('input');
+ var audioSelect = row.cells[2].querySelector('select');
+ if (timeInput && audioSelect) {
+ reminders.push({
+ condition: condition,
+ time: timeInput.value || 0,
+ audio: audioSelect.value
+ });
+ }
+ }
+ if (reminders.length === 0) {
+ errorSystem.show('请添加至少一个提醒策略');
+ return;
+ }
+ // 保存到 Cookie 并更新提醒队列
+ setCookie("examReminders", encodeURIComponent(JSON.stringify(reminders)), 365);
+ loadRemindersToQueue(reminders);
+ errorSystem.show('提醒设置已保存');
+ } catch (e) {
+ errorSystem.show('保存设置失败: ' + e.message);
+ }
+}
+
+function loadRemindersToQueue(reminders) {
+ // 获取当前或下一个考试
+ const examConfig = window.examConfigData;
+ if (!examConfig || !Array.isArray(examConfig.examInfos)) return;
+ const now = Date.now();
+ let targetExam = null;
+ for (const exam of examConfig.examInfos) {
+ const start = new Date(exam.start).getTime();
+ const end = new Date(exam.end).getTime();
+ if (now < end) {
+ targetExam = exam;
+ break;
+ }
+ }
+ if (!targetExam) return;
+ reminders.forEach(function(reminder) {
+ let reminderTime;
+ switch (reminder.condition) {
+ case 'beforeStart':
+ reminderTime = new Date(targetExam.start).getTime() - reminder.time * 60000;
+ break;
+ case 'beforeEnd':
+ reminderTime = new Date(targetExam.end).getTime() - reminder.time * 60000;
+ break;
+ case 'afterEnd':
+ reminderTime = new Date(targetExam.end).getTime() + reminder.time * 60000;
+ break;
+ case 'start':
+ reminderTime = new Date(targetExam.start).getTime();
+ break;
+ case 'end':
+ reminderTime = new Date(targetExam.end).getTime();
+ break;
+ }
+ if (reminderTime > now) {
+ reminderQueue.addReminder({ time: reminderTime, condition: reminder.condition, audio: reminder.audio });
+ }
+ });
+}
+
+// 页面加载时自动填充提醒表格
+document.addEventListener("DOMContentLoaded", () => {
+ // 加载提醒设置
+ const reminderCookie = getCookie("examReminders");
+ if (reminderCookie) {
+ const reminders = JSON.parse(decodeURIComponent(reminderCookie));
+ if (Array.isArray(reminders)) {
+ var table = document.getElementById('reminderTable');
+ while (table.rows.length > 2) {
+ table.deleteRow(1);
+ }
+ fetch('audio_files.json')
+ .then(response => response.json())
+ .then(audioFiles => {
+ const validAudioTypes = Object.keys(audioFiles);
+ const defaultAudio = validAudioTypes[0];
+ reminders.forEach(function(reminder) {
+ if (!validAudioTypes.includes(reminder.audio)) {
+ reminder.audio = defaultAudio;
+ }
+ var row = table.insertRow(table.rows.length - 1);
+ let audioOptions = validAudioTypes
+ .map(audio => ``)
+ .join('');
+ row.innerHTML = `
+
+
+ |
+ |
+
+
+ |
+ |
+ `;
+ row.cells[0].querySelector('select').addEventListener('change', function() {
+ row.cells[1].querySelector('input').disabled = this.value === 'start' || this.value === 'end';
+ row.cells[1].querySelector('input').placeholder = this.value === 'start' || this.value === 'end' ? '-' : '分钟';
+ });
+ });
+ loadRemindersToQueue(reminders);
+ });
+ }
+ }
+});
diff --git a/exam/Scripts/utils.js b/exam/Scripts/utils.js
index 68e8cb9..4d0d303 100644
--- a/exam/Scripts/utils.js
+++ b/exam/Scripts/utils.js
@@ -16,6 +16,8 @@ function getCookie(name) {
return null;
}
+// 保持 setCookie/getCookie 兼容提醒设置
+
function formatTimeWithoutSeconds(time) {
return time.slice(0, -3);
}
diff --git a/exam/Styles/ealg/dark.css b/exam/Styles/ealg/dark.css
index 0a7bd17..2cfac16 100644
--- a/exam/Styles/ealg/dark.css
+++ b/exam/Styles/ealg/dark.css
@@ -33,51 +33,6 @@ body::-webkit-scrollbar {
display: none;
}
-#fullscreen-btn, #settings-btn {
- position: absolute;
- top: 20px;
- padding: 12px 24px;
- font-size: 1rem;
- cursor: pointer;
- background-color: #404040;
- color: #E6E1E5;
- border: none;
- border-radius: 20px;
- box-shadow: 0 1px 3px rgba(0,0,0,0.3);
- transition: all 0.2s ease;
- z-index: 1001;
- display: flex;
- align-items: center;
-}
-
-#fullscreen-btn::before {
- content: "fullscreen";
- font-family: 'Material Icons';
- font-size: 20px;
- margin-right: 4px;
-}
-
-#settings-btn::before {
- content: "settings";
- font-family: 'Material Icons';
- font-size: 20px;
- margin-right: 4px;
-}
-
-#fullscreen-btn {
- right: 20px;
-}
-
-#settings-btn {
- right: 140px;
-}
-
-#settings-btn:hover, #fullscreen-btn:hover {
- background-color: #4A4A4A;
- transform: translateY(-1px);
- box-shadow: 0 2px 6px rgba(0,0,0,0.4);
-}
-
.container {
padding: 24px;
max-width: 90%;
@@ -667,4 +622,409 @@ input:checked + .slider:before {
.count-btn .material-icons {
font-size: 16px;
+}
+
+.settings-modal {
+ display: none;
+ position: fixed;
+ z-index: 2000;
+ left: 0;
+ top: 0;
+ width: 100vw;
+ height: 100vh;
+ background-color: rgba(0,0,0,0.6);
+ backdrop-filter: blur(8px);
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
+
+#reminder-modal-content {
+ background: #404040;
+ padding: 32px 48px 32px 32px;
+ border-radius: 28px;
+ width: 600px;
+ max-height: 60vh;
+ overflow-y: auto;
+ box-shadow: 0 8px 24px rgba(0,0,0,0.4);
+ z-index: 2100;
+}
+
+@media (max-width: 700px) {
+ #reminder-modal-content {
+ width: 95vw;
+ padding: 16px;
+ }
+}
+
+/* 补全提醒设置弹窗样式 */
+.reminder-modal {
+ display: none;
+ position: fixed;
+ z-index: 2000;
+ left: 0;
+ top: 0;
+ width: 100vw;
+ height: 100vh;
+ background-color: rgba(0,0,0,0.6);
+ backdrop-filter: blur(8px);
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
+
+.reminder-modal.show {
+ display: flex;
+}
+
+#reminder-modal-content {
+ background: #404040;
+ padding: 32px 48px 32px 32px;
+ border-radius: 28px;
+ width: 800px;
+ max-width: 90vw;
+ max-height: 60vh;
+ overflow-y: auto;
+ box-shadow: 0 8px 24px rgba(0,0,0,0.4);
+ z-index: 2100;
+}
+
+#reminder-modal-content::-webkit-scrollbar {
+ width: 8px;
+}
+
+#reminder-modal-content::-webkit-scrollbar-track {
+ background: transparent;
+ margin: 4px;
+}
+
+#reminder-modal-content::-webkit-scrollbar-thumb {
+ background: #4A4458;
+ border-radius: 8px;
+ border: 2px solid #2B2930;
+}
+
+#reminder-modal-content::-webkit-scrollbar-thumb:hover {
+ background: #635B70;
+}
+
+#reminder-modal-content h3 {
+ margin: 0 0 24px;
+ color: #E6E1E5;
+ font-size: 24px;
+ font-weight: 400;
+}
+
+#reminder-modal-content label {
+ display: flex;
+ align-items: center;
+ gap: 16px;
+ margin: 16px 0;
+ font-size: 16px;
+ color: #E6E1E5;
+}
+
+#reminder-modal-content input[type="number"],
+#reminder-modal-content input[type="text"] {
+ font-size: 1.8rem;
+ padding: 12px 16px;
+ margin: 8px 0 24px;
+ width: 100%;
+ box-sizing: border-box;
+ border: 2px solid #4A4458;
+ border-radius: 12px;
+ background-color: #332D41;
+ color: #E6E1E5;
+ transition: all 0.2s ease;
+}
+
+#reminder-modal-content input:focus {
+ outline: none;
+ border-color: #D0BCFF;
+ background-color: #4A4458;
+}
+
+.reminder-button-group {
+ display: flex;
+ justify-content: flex-end;
+ gap: 16px;
+ margin-top: 32px;
+ position: relative;
+ background-color: #404040;
+ padding: 16px 0;
+ border-top: 1px solid #555555;
+}
+
+#save-reminder-btn, #close-reminder-btn {
+ padding: 12px 24px;
+ border-radius: 20px;
+ font-size: 16px;
+ font-weight: 500;
+ border: none;
+ cursor: pointer;
+ transition: all 0.2s ease;
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ background-color: #404040;
+ color: #E6E1E5;
+}
+
+#save-reminder-btn::before {
+ content: "✓";
+ font-size: 18px;
+}
+
+#close-reminder-btn::before {
+ content: "✕";
+ font-size: 18px;
+}
+
+#save-reminder-btn:hover, #close-reminder-btn:hover {
+ background-color: #4A4A4A;
+ transform: translateY(-1px);
+ box-shadow: 0 2px 6px rgba(0,0,0,0.4);
+}
+
+@media (max-width: 700px) {
+ #reminder-modal-content {
+ width: 95vw;
+ padding: 16px;
+ }
+}
+
+.top-btn-group {
+ position: fixed;
+ top: 20px;
+ right: 20px;
+ display: flex;
+ flex-direction: row;
+ gap: 16px;
+ z-index: 1002;
+}
+
+.top-btn-group button {
+ padding: 12px 24px;
+ font-size: 1rem;
+ cursor: pointer;
+ background-color: #404040;
+ color: #E6E1E5;
+ border: none;
+ border-radius: 20px;
+ box-shadow: 0 1px 3px rgba(0,0,0,0.3);
+ transition: all 0.2s ease;
+ display: flex;
+ align-items: center;
+ white-space: nowrap;
+}
+
+.top-btn-group button::before {
+ font-family: 'Material Icons';
+ font-size: 20px;
+ margin-right: 8px;
+}
+
+.top-btn-group button:hover {
+ background-color: #4A4A4A;
+ transform: translateY(-1px);
+ box-shadow: 0 2px 6px rgba(0,0,0,0.4);
+}
+
+#fullscreen-btn::before {
+ content: "fullscreen";
+}
+
+#reminder-settings-btn::before {
+ content: "notifications";
+}
+
+#settings-btn::before {
+ content: "settings";
+}
+
+/* 修改提醒弹窗样式 */
+.reminder-modal {
+ display: none;
+ position: fixed;
+ z-index: 2000;
+ left: 0;
+ top: 0;
+ width: 100vw;
+ height: 100vh;
+ background-color: rgba(0,0,0,0.6);
+ backdrop-filter: blur(8px);
+}
+
+#reminder-modal-content {
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ transform: translate(-50%, -50%);
+ background: #404040;
+ padding: 32px 48px 32px 32px;
+ border-radius: 28px;
+ width: 800px;
+ max-width: 90vw;
+ max-height: 80vh;
+ overflow-y: auto;
+ box-shadow: 0 8px 24px rgba(0,0,0,0.4);
+}
+
+/* 提醒表格样式 */
+.reminder-table {
+ width: 100%;
+ border-collapse: collapse;
+ margin-bottom: 20px;
+}
+
+.reminder-table th,
+.reminder-table td {
+ padding: 12px;
+ text-align: left;
+ border-bottom: 1px solid #555555;
+ font-size: 14px;
+ line-height: 36px;
+ vertical-align: middle;
+}
+
+.reminder-table th {
+ font-weight: 500;
+ color: #E6E1E5;
+ font-size: 14px;
+}
+
+.reminder-table select,
+.reminder-table input {
+ width: 100%;
+ height: 36px;
+ padding: 0 12px;
+ font-size: 14px;
+ background-color: #332D41;
+ color: #E6E1E5;
+ border: 2px solid #4A4458;
+ border-radius: 8px;
+ transition: all 0.2s ease;
+ box-sizing: border-box;
+}
+
+/* 提醒时间输入框独立样式 */
+.reminder-table .reminder-time-input {
+ width: 30px;
+ height: 36px;
+ padding: 0 12px;
+ font-size: 14px;
+ background-color: #332D41;
+ color: #E6E1E5;
+ border: 2px solid #4A4458;
+ border-radius: 8px;
+ transition: all 0.2s ease;
+ box-sizing: border-box;
+ text-align: center;
+}
+
+.reminder-table .reminder-time-input:focus {
+ outline: none;
+ border-color: #D0BCFF;
+ background-color: #4A4458;
+}
+
+.reminder-table button {
+ height: 36px;
+ min-width: 80px;
+ padding: 0 16px;
+ font-size: 14px;
+ background-color: #404040;
+ color: #E6E1E5;
+ border: none;
+ border-radius: 8px;
+ cursor: pointer;
+ transition: all 0.2s ease;
+ white-space: nowrap;
+}
+
+.reminder-table select:focus,
+.reminder-table input:focus {
+ outline: none;
+ border-color: #D0BCFF;
+ background-color: #4A4458;
+}
+
+.reminder-table button {
+ padding: 8px 16px;
+ font-size: 14px;
+ background-color: #404040;
+ color: #E6E1E5;
+ border: none;
+ border-radius: 16px;
+ cursor: pointer;
+ transition: all 0.2s ease;
+}
+
+.reminder-table button:hover {
+ background-color: #4A4A4A;
+ transform: translateY(-1px);
+ box-shadow: 0 2px 6px rgba(0,0,0,0.4);
+}
+
+.action-btn {
+ width: 100%;
+ padding: 12px;
+ font-size: 14px;
+ background-color: #404040;
+ color: #E6E1E5;
+ border: none;
+ border-radius: 16px;
+ cursor: pointer;
+ transition: all 0.2s ease;
+ margin-top: 12px;
+}
+
+.action-btn:hover {
+ background-color: #4A4A4A;
+ transform: translateY(-1px);
+ box-shadow: 0 2px 6px rgba(0,0,0,0.4);
+}
+
+.action-btn {
+ height: 36px;
+ font-size: 14px;
+ line-height: 36px;
+ padding: 0 16px;
+}
+
+/* 提醒表格的时间输入框样式 */
+.reminder-table td input[type="number"] {
+ width: 80px !important;
+ text-align: center !important;
+ padding: 0 8px !important;
+ margin: 0 auto !important;
+ display: block !important;
+ -moz-appearance: textfield !important;
+}
+
+.reminder-table td input[type="number"]::-webkit-outer-spin-button,
+.reminder-table td input[type="number"]::-webkit-inner-spin-button {
+ -webkit-appearance: none;
+ margin: 0;
+}
+
+/* 确保修改其他输入框和选择框不受影响 */
+.reminder-table td select {
+ min-width: 200px;
+}
+
+.reminder-table td:nth-child(1) {
+ width: 50%;
+}
+
+.reminder-table td:nth-child(2) {
+ width: 15%;
+}
+
+.reminder-table td:nth-child(3) {
+ width: 25%;
+}
+
+.reminder-table td:nth-child(4) {
+ width: 10%;
}
\ No newline at end of file
diff --git a/exam/Styles/ealg/light.css b/exam/Styles/ealg/light.css
index dfe585a..510d322 100644
--- a/exam/Styles/ealg/light.css
+++ b/exam/Styles/ealg/light.css
@@ -33,9 +33,27 @@ body::-webkit-scrollbar {
display: none;
}
-#fullscreen-btn, #settings-btn {
- position: absolute;
+/* 删除这些样式
+#fullscreen-btn, #settings-btn { ... }
+#fullscreen-btn { ... }
+#settings-btn { ... }
+#settings-btn:hover, #fullscreen-btn:hover { ... }
+#settings-btn::before { ... }
+#fullscreen-btn::before { ... }
+*/
+
+/* 新的按钮组样式 */
+.top-btn-group {
+ position: fixed;
top: 20px;
+ right: 20px;
+ display: flex;
+ flex-direction: row;
+ gap: 16px;
+ z-index: 1002;
+}
+
+.top-btn-group button {
padding: 12px 24px;
font-size: 1rem;
cursor: pointer;
@@ -45,37 +63,33 @@ body::-webkit-scrollbar {
border-radius: 20px;
box-shadow: 0 1px 3px rgba(0,0,0,0.1);
transition: all 0.2s ease;
- z-index: 1001;
display: flex;
align-items: center;
+ white-space: nowrap;
}
-#fullscreen-btn {
- right: 20px;
+.top-btn-group button::before {
+ font-family: 'Material Icons';
+ font-size: 20px;
+ margin-right: 8px;
}
-#settings-btn {
- right: 140px;
-}
-
-#settings-btn:hover, #fullscreen-btn:hover {
+.top-btn-group button:hover {
background-color: #D0BCFF;
transform: translateY(-1px);
box-shadow: 0 2px 6px rgba(0,0,0,0.2);
}
-#settings-btn::before {
- content: "settings";
- font-family: 'Material Icons';
- font-size: 20px;
- margin-right: 4px;
-}
-
#fullscreen-btn::before {
content: "fullscreen";
- font-family: 'Material Icons';
- font-size: 20px;
- margin-right: 4px;
+}
+
+#reminder-settings-btn::before {
+ content: "notifications";
+}
+
+#settings-btn::before {
+ content: "settings";
}
.container {
@@ -667,4 +681,212 @@ input:checked + .slider:before {
color: #1C1B1F;
border: 2px solid #E8DEF8;
border-radius: 8px;
+}
+
+.settings-modal {
+ display: none;
+ position: fixed;
+ z-index: 2000;
+ left: 0;
+ top: 0;
+ width: 100vw;
+ height: 100vh;
+ background-color: rgba(0,0,0,0.3);
+ backdrop-filter: blur(8px);
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
+
+#reminder-modal-content {
+ background: #FFFFFF;
+ padding: 32px 48px 32px 32px;
+ border-radius: 28px;
+ width: 600px;
+ max-height: 60vh;
+ overflow-y: auto;
+ box-shadow: 0 8px 24px rgba(0,0,0,0.2);
+ z-index: 2100;
+}
+
+#reminder-modal-content {
+ width: 800px;
+ max-width: 90vw;
+}
+
+@media (max-width: 700px) {
+ #reminder-modal-content {
+ width: 95vw;
+ padding: 16px;
+ }
+}
+
+.top-btn-group {
+ position: fixed;
+ top: 20px;
+ right: 20px;
+ display: flex;
+ gap: 16px;
+ z-index: 1002;
+}
+
+.top-btn-group button {
+ padding: 12px 24px;
+ font-size: 1rem;
+ cursor: pointer;
+ background-color: #E8DEF8;
+ color: #1C1B1F;
+ border: none;
+ border-radius: 20px;
+ box-shadow: 0 1px 3px rgba(0,0,0,0.1);
+ transition: all 0.2s ease;
+ display: flex;
+ align-items: center;
+}
+
+.top-btn-group button:hover {
+ background-color: #D0BCFF;
+ transform: translateY(-1px);
+ box-shadow: 0 2px 6px rgba(0,0,0,0.2);
+}
+
+/* 按钮图标 */
+.top-btn-group button::before {
+ font-family: 'Material Icons';
+ font-size: 20px;
+ margin-right: 8px;
+}
+
+#fullscreen-btn::before {
+ content: "fullscreen";
+}
+
+#reminder-settings-btn::before {
+ content: "notifications";
+}
+
+#settings-btn::before {
+ content: "settings";
+}
+
+/* 提醒表格样式 */
+.reminder-table {
+ width: 100%;
+ border-collapse: collapse;
+ margin-bottom: 20px;
+}
+
+.reminder-table th,
+.reminder-table td {
+ padding: 12px;
+ text-align: left;
+ border-bottom: 1px solid #E8DEF8;
+ font-size: 14px;
+ line-height: 36px;
+ vertical-align: middle;
+}
+
+.reminder-table th {
+ font-weight: 500;
+ color: #1C1B1F;
+ font-size: 14px;
+}
+
+.reminder-table select,
+.reminder-table input {
+ width: 100%;
+ height: 36px;
+ padding: 0 12px;
+ font-size: 14px;
+ background-color: #FFFFFF;
+ color: #1C1B1F;
+ border: 2px solid #E8DEF8;
+ border-radius: 8px;
+ transition: all 0.2s ease;
+ box-sizing: border-box;
+}
+
+.reminder-table button {
+ height: 36px;
+ min-width: 80px;
+ padding: 0 16px;
+ font-size: 14px;
+ background-color: #E8DEF8;
+ color: #1C1B1F;
+ border: none;
+ border-radius: 8px;
+ cursor: pointer;
+ transition: all 0.2s ease;
+ white-space: nowrap;
+}
+
+.action-btn {
+ height: 36px;
+ font-size: 14px;
+ line-height: 36px;
+ padding: 0 16px;
+}
+
+.action-btn:hover {
+ background-color: #D0BCFF;
+ transform: translateY(-1px);
+ box-shadow: 0 2px 6px rgba(0,0,0,0.2);
+}
+
+/* 提醒时间输入框独立样式 */
+.reminder-table .reminder-time-input {
+ width: 80px;
+ height: 36px;
+ padding: 0 12px;
+ font-size: 14px;
+ background-color: #FFFFFF;
+ color: #1C1B1F;
+ border: 2px solid #E8DEF8;
+ border-radius: 8px;
+ transition: all 0.2s ease;
+ box-sizing: border-box;
+ text-align: center;
+}
+
+.reminder-table .reminder-time-input:focus {
+ outline: none;
+ border-color: #6750A4;
+ background-color: #F7F2FA;
+}
+
+/* 提醒表格的时间输入框样式 */
+.reminder-table td input[type="number"] {
+ width: 80px !important;
+ text-align: center !important;
+ padding: 0 8px !important;
+ -moz-appearance: textfield !important;
+ margin: 0 auto !important;
+ display: block !important;
+}
+
+.reminder-table td input[type="number"]::-webkit-outer-spin-button,
+.reminder-table td input[type="number"]::-webkit-inner-spin-button {
+ -webkit-appearance: none;
+ margin: 0;
+}
+
+/* 确保修改其他输入框和选择框不受影响 */
+.reminder-table td select {
+ min-width: 200px;
+}
+
+.reminder-table td:nth-child(1) {
+ width: 50%;
+}
+
+.reminder-table td:nth-child(2) {
+ width: 15%;
+}
+
+.reminder-table td:nth-child(3) {
+ width: 25%;
+}
+
+.reminder-table td:nth-child(4) {
+ width: 10%;
}
\ No newline at end of file
diff --git a/notification/audio/15min_left.mp3 b/exam/audio/15min_left.mp3
similarity index 100%
rename from notification/audio/15min_left.mp3
rename to exam/audio/15min_left.mp3
diff --git a/notification/audio/30min_left.mp3 b/exam/audio/30min_left.mp3
similarity index 100%
rename from notification/audio/30min_left.mp3
rename to exam/audio/30min_left.mp3
diff --git a/notification/audio/classstart.mp3 b/exam/audio/classstart.mp3
similarity index 100%
rename from notification/audio/classstart.mp3
rename to exam/audio/classstart.mp3
diff --git a/notification/audio/end.mp3 b/exam/audio/end.mp3
similarity index 100%
rename from notification/audio/end.mp3
rename to exam/audio/end.mp3
diff --git a/notification/audio/hedui_eng.mp3 b/exam/audio/hedui_eng.mp3
similarity index 100%
rename from notification/audio/hedui_eng.mp3
rename to exam/audio/hedui_eng.mp3
diff --git a/notification/audio/hedui_noeng.mp3 b/exam/audio/hedui_noeng.mp3
similarity index 100%
rename from notification/audio/hedui_noeng.mp3
rename to exam/audio/hedui_noeng.mp3
diff --git a/notification/audio/jinchang.mp3 b/exam/audio/jinchang.mp3
similarity index 100%
rename from notification/audio/jinchang.mp3
rename to exam/audio/jinchang.mp3
diff --git a/notification/audio/start.mp3 b/exam/audio/start.mp3
similarity index 100%
rename from notification/audio/start.mp3
rename to exam/audio/start.mp3
diff --git a/notification/audio/zhanshikemudai.mp3 b/exam/audio/zhanshikemudai.mp3
similarity index 100%
rename from notification/audio/zhanshikemudai.mp3
rename to exam/audio/zhanshikemudai.mp3
diff --git a/notification/audio_files.json b/exam/audio_files.json
similarity index 100%
rename from notification/audio_files.json
rename to exam/audio_files.json
diff --git a/exam/exam_config.json b/exam/exam_config.json
index a1f5016..d0a5242 100644
--- a/exam/exam_config.json
+++ b/exam/exam_config.json
@@ -5,7 +5,7 @@
"examInfos": [
{
"name": "语文",
- "start": "2025-05-06T07:30:00",
+ "start": "2025-04-27T01:20:00",
"end": "2025-05-06T10:00:00"
},
{
diff --git a/exam/index.html b/exam/index.html
index 8a43305..6f37cdc 100644
--- a/exam/index.html
+++ b/exam/index.html
@@ -12,9 +12,13 @@
+
+
+
+
+
+
-
-
考试安排
@@ -156,9 +160,34 @@
+
+
+
+
提醒设置
+
+
+ 提醒条件 |
+ 时间(分钟) |
+ 音频选择 |
+ 操作 |
+
+
+ |
+
+
+
+
+
+
+
+
+
+
+
+