mirror of
https://github.com/ExamAware/ExamSchedule.git
synced 2025-04-29 02:56:32 +00:00
style: 更新时间页面样式,调整背景颜色和透明度,优化按钮样式和文本颜色
This commit is contained in:
parent
d3122a47ff
commit
c68f6a4e72
596
exam/x.html
596
exam/x.html
@ -1,596 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>课程状态系统完整版</title>
|
||||
<style>
|
||||
/* 基础样式 */
|
||||
body {
|
||||
font-family: 'Segoe UI', Arial, sans-serif;
|
||||
margin: 0;
|
||||
padding: 20px;
|
||||
background: #f5f7fa;
|
||||
color: #2d3436;
|
||||
}
|
||||
.container {
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* 状态显示框 */
|
||||
.status-box {
|
||||
background: linear-gradient(145deg, #ffffff, #f8f9fa);
|
||||
border: 1px solid #e0e6ed;
|
||||
padding: 30px;
|
||||
margin: 20px 0;
|
||||
border-radius: 16px;
|
||||
box-shadow: 0 8px 24px rgba(0,0,0,0.06);
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
.time-display {
|
||||
font-size: 48px;
|
||||
color: #2c3e50;
|
||||
font-weight: 700;
|
||||
margin: 15px 0;
|
||||
text-align: center;
|
||||
letter-spacing: 2px;
|
||||
text-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
||||
}
|
||||
.status-label {
|
||||
font-size: 28px;
|
||||
text-align: center;
|
||||
margin: 15px 0;
|
||||
color: #57606f;
|
||||
}
|
||||
|
||||
/* 课程表格 */
|
||||
.schedule-table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
margin: 25px 0;
|
||||
background: white;
|
||||
border-radius: 12px;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 4px 12px rgba(0,0,0,0.08);
|
||||
}
|
||||
.schedule-table th {
|
||||
background: #f8f9fa;
|
||||
padding: 16px;
|
||||
color: #57606f;
|
||||
font-weight: 600;
|
||||
border-bottom: 2px solid #e0e6ed;
|
||||
}
|
||||
.schedule-table td {
|
||||
padding: 14px;
|
||||
border-bottom: 1px solid #f1f3f6;
|
||||
}
|
||||
.current-class {
|
||||
background: #e8f5e9 !important;
|
||||
position: relative;
|
||||
}
|
||||
.current-class:after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
height: 100%;
|
||||
width: 4px;
|
||||
background: #2ecc71;
|
||||
}
|
||||
.future-class {
|
||||
background: #f8f9fa !important;
|
||||
}
|
||||
.past-class {
|
||||
background: #fafafa !important;
|
||||
color: #a4b0be;
|
||||
}
|
||||
|
||||
/* 全屏模式 */
|
||||
.fullscreen-mode {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: #ffffff;
|
||||
z-index: 9999;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
.fullscreen-mode .status-box {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border: none;
|
||||
box-shadow: none;
|
||||
border-radius: 0;
|
||||
padding: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
background: none;
|
||||
}
|
||||
.fullscreen-mode .time-display {
|
||||
font-size: 25vw;
|
||||
line-height: 0.9;
|
||||
color: #2c3e50;
|
||||
}
|
||||
.fullscreen-mode .status-label {
|
||||
font-size: 6vw;
|
||||
margin-top: 4vw;
|
||||
color: #57606f;
|
||||
}
|
||||
.fullscreen-mode .control-bar,
|
||||
.fullscreen-mode .settings-panel,
|
||||
.fullscreen-mode .schedule-table {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/* 控制按钮 */
|
||||
.control-bar {
|
||||
position: fixed;
|
||||
top: 20px;
|
||||
right: 20px;
|
||||
z-index: 10000;
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
}
|
||||
.control-btn {
|
||||
background: linear-gradient(135deg, #3498db, #2980b9);
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 12px 24px;
|
||||
border-radius: 8px;
|
||||
cursor: pointer;
|
||||
font-size: 15px;
|
||||
font-weight: 500;
|
||||
transition: all 0.2s ease;
|
||||
box-shadow: 0 4px 12px rgba(52,152,219,0.25);
|
||||
}
|
||||
.control-btn:hover {
|
||||
transform: translateY(-1px);
|
||||
box-shadow: 0 6px 16px rgba(52,152,219,0.35);
|
||||
}
|
||||
|
||||
/* 设置面板 */
|
||||
.settings-panel {
|
||||
background: rgba(255,255,255,0.95);
|
||||
padding: 25px;
|
||||
margin: 25px 0;
|
||||
border-radius: 12px;
|
||||
border: 1px solid #e0e6ed;
|
||||
backdrop-filter: blur(8px);
|
||||
}
|
||||
.settings-panel h3 {
|
||||
margin: 0 0 20px;
|
||||
color: #2c3e50;
|
||||
font-size: 20px;
|
||||
}
|
||||
.settings-panel label {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
margin: 12px 0;
|
||||
font-size: 16px;
|
||||
color: #57606f;
|
||||
}
|
||||
.settings-panel input[type="checkbox"] {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
accent-color: #3498db;
|
||||
}
|
||||
|
||||
/* 错误提示 */
|
||||
.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;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="error-container">
|
||||
<div class="error-content" id="errorMessage"></div>
|
||||
</div>
|
||||
|
||||
<div class="container">
|
||||
<div class="control-bar">
|
||||
<button class="control-btn" onclick="toggleFullscreen()">全屏</button>
|
||||
<button class="control-btn" onclick="testSound('classStart')">测试上课铃</button>
|
||||
<button class="control-btn" onclick="testSound('classEnd')">测试下课铃</button>
|
||||
</div>
|
||||
|
||||
<div class="status-box">
|
||||
<div class="status-label" id="statusLabel">正在初始化...</div>
|
||||
<div class="time-display" id="timeDisplay">--:--</div>
|
||||
<div id="timeDescription" style="text-align:center;color:#a4b0be;"></div>
|
||||
</div>
|
||||
|
||||
<div class="settings-panel">
|
||||
<h3>系统设置</h3>
|
||||
<label>
|
||||
<input type="checkbox" id="classBell"> 启用上课铃声
|
||||
</label>
|
||||
<br>
|
||||
<label>
|
||||
<input type="checkbox" id="breakBell"> 启用下课铃声
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<table class="schedule-table" id="scheduleTable">
|
||||
<tr>
|
||||
<th>课程名称</th>
|
||||
<th>时间段</th>
|
||||
<th>状态</th>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// 错误处理系统
|
||||
var errorSystem = {
|
||||
show: function(message) {
|
||||
try {
|
||||
var container = document.querySelector('.error-container');
|
||||
var content = document.getElementById('errorMessage');
|
||||
content.textContent = message;
|
||||
container.style.display = 'flex';
|
||||
setTimeout(this.hide, 5000);
|
||||
} catch(e) {
|
||||
console.error('错误提示系统异常:', e);
|
||||
}
|
||||
},
|
||||
hide: function() {
|
||||
var container = document.querySelector('.error-container');
|
||||
if (container) container.style.display = 'none';
|
||||
}
|
||||
};
|
||||
|
||||
// 新增:课程配置数组
|
||||
var courseSchedule = [
|
||||
{ name: "第一节课", start: "08:00", end: "08:50" },
|
||||
{ name: "第二节课", start: "09:00", end: "09:50" },
|
||||
{ name: "第三节课", start: "10:10", end: "11:00" },
|
||||
{ name: "第四节课", start: "11:10", end: "12:00" },
|
||||
{ name: "第一节课", start: "13:30", end: "14:20" },
|
||||
{ name: "第二节课", start: "14:30", end: "15:20" },
|
||||
{ name: "第三节课", start: "15:40", end: "16:30" },
|
||||
{ name: "第四节课", start: "16:40", end: "17:30" },
|
||||
{ name: "第一节课", start: "18:00", end: "18:50" },
|
||||
{ name: "第二节课", start: "19:00", end: "19:50" },
|
||||
{ name: "第三节课", start: "20:10", end: "21:00" },
|
||||
{ name: "第四节课", start: "21:10", end: "22:00" }
|
||||
];
|
||||
|
||||
// 恢复使用原来的音频系统
|
||||
var audioController = (function() {
|
||||
var audioPool = [];
|
||||
var maxPoolSize = 3;
|
||||
var soundFiles = {
|
||||
classStart: 'class_start.mp3',
|
||||
classEnd: 'class_end.mp3'
|
||||
};
|
||||
|
||||
function init() {
|
||||
try {
|
||||
Object.keys(soundFiles).forEach(function(type) {
|
||||
for (var i = 0; i < 2; i++) {
|
||||
createAudio(type);
|
||||
}
|
||||
});
|
||||
} catch(e) {
|
||||
errorSystem.show('音频初始化失败: ' + e.message);
|
||||
}
|
||||
}
|
||||
|
||||
function createAudio(type) {
|
||||
var audio = document.createElement('audio');
|
||||
audio.style.display = 'none';
|
||||
audio.preload = 'auto';
|
||||
audio.src = soundFiles[type];
|
||||
var retryCount = 0;
|
||||
function loadAudio() {
|
||||
try {
|
||||
audio.load();
|
||||
} catch(e) {
|
||||
if (retryCount++ < 3) {
|
||||
setTimeout(loadAudio, 1000);
|
||||
}
|
||||
}
|
||||
}
|
||||
audio.addEventListener('error', function() {
|
||||
if (retryCount++ < 3) {
|
||||
setTimeout(loadAudio, 1000);
|
||||
}
|
||||
});
|
||||
document.body.appendChild(audio);
|
||||
loadAudio();
|
||||
audioPool.push(audio);
|
||||
return audio;
|
||||
}
|
||||
|
||||
function play(type) {
|
||||
try {
|
||||
var audio = audioPool.find(function(a) { return a.paused; });
|
||||
if (!audio) {
|
||||
if (audioPool.length < maxPoolSize) {
|
||||
audio = createAudio(type);
|
||||
} else {
|
||||
return errorSystem.show('系统繁忙,请稍后再试');
|
||||
}
|
||||
}
|
||||
audio.src = soundFiles[type];
|
||||
try {
|
||||
audio.play();
|
||||
} catch(e) {
|
||||
errorSystem.show('播放失败: ' + e.message);
|
||||
}
|
||||
} catch(e) {
|
||||
errorSystem.show('音频系统错误: ' + e.message);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
init: init,
|
||||
play: play
|
||||
};
|
||||
})();
|
||||
|
||||
audioController.init();
|
||||
|
||||
// 全局状态变量
|
||||
var isFullscreen = false, currentCourse = null, lastCourse = null, timer = null, lastUpdate = Date.now();
|
||||
|
||||
// 新增:安全更新循环函数
|
||||
function safeUpdate() {
|
||||
try {
|
||||
var now = Date.now();
|
||||
updateCourseStatus();
|
||||
updateDisplay();
|
||||
var nextTick = Math.max(1000 - (Date.now() - now), 50);
|
||||
timer = setTimeout(safeUpdate, nextTick);
|
||||
lastUpdate = now;
|
||||
} catch (e) {
|
||||
errorSystem.show('更新循环错误: ' + e.message);
|
||||
}
|
||||
}
|
||||
|
||||
// 新增:解析时间字符串
|
||||
function parseTime(timeStr) {
|
||||
try {
|
||||
var now = new Date();
|
||||
var parts = timeStr.split(':');
|
||||
return new Date(
|
||||
now.getFullYear(),
|
||||
now.getMonth(),
|
||||
now.getDate(),
|
||||
parseInt(parts[0]),
|
||||
parseInt(parts[1]),
|
||||
0
|
||||
);
|
||||
} catch (e) {
|
||||
errorSystem.show('时间解析错误: ' + e.message);
|
||||
return new Date();
|
||||
}
|
||||
}
|
||||
|
||||
// 新增:更新当前课程状态函数
|
||||
function updateCourseStatus() {
|
||||
try {
|
||||
var now = new Date();
|
||||
currentCourse = null;
|
||||
for (var i = 0; i < courseSchedule.length; i++) {
|
||||
var course = courseSchedule[i],
|
||||
start = parseTime(course.start),
|
||||
end = parseTime(course.end);
|
||||
if (end < start) end.setDate(end.getDate() + 1);
|
||||
if (now >= start && now <= end) {
|
||||
currentCourse = course;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (currentCourse !== lastCourse) {
|
||||
handleStatusChange();
|
||||
lastCourse = currentCourse;
|
||||
}
|
||||
} catch (e) {
|
||||
errorSystem.show('课程状态更新失败: ' + e.message);
|
||||
}
|
||||
}
|
||||
|
||||
// 在状态变化处理函数中使用 audioController 而非 audioContext
|
||||
function handleStatusChange() {
|
||||
try {
|
||||
if (!currentCourse && localStorage.breakBell === 'true') {
|
||||
audioController.play('classEnd');
|
||||
} else if (currentCourse && localStorage.classBell === 'true') {
|
||||
audioController.play('classStart');
|
||||
}
|
||||
} catch (e) {
|
||||
errorSystem.show('状态变化处理错误: ' + e.message);
|
||||
}
|
||||
}
|
||||
|
||||
// 新增:界面更新函数
|
||||
function updateDisplay() {
|
||||
try {
|
||||
var now = new Date(),
|
||||
timeDisplay = document.getElementById('timeDisplay'),
|
||||
statusLabel = document.getElementById('statusLabel'),
|
||||
timeDesc = document.getElementById('timeDescription');
|
||||
if (currentCourse) {
|
||||
var endTime = parseTime(currentCourse.end),
|
||||
remain = endTime - now;
|
||||
statusLabel.textContent = currentCourse.name + ' 进行中';
|
||||
timeDisplay.textContent = formatTime(remain);
|
||||
timeDesc.textContent = '剩余时间';
|
||||
} else {
|
||||
statusLabel.textContent = '课间休息中';
|
||||
var nextCourse = getNextCourse();
|
||||
if (nextCourse) {
|
||||
var startTime = parseTime(nextCourse.start),
|
||||
remain = startTime - now;
|
||||
timeDisplay.textContent = formatTime(remain);
|
||||
timeDesc.textContent = '距离 ' + nextCourse.name;
|
||||
} else {
|
||||
timeDisplay.textContent = '00:00';
|
||||
timeDesc.textContent = '今日课程已结束';
|
||||
}
|
||||
}
|
||||
updateScheduleTable();
|
||||
} catch (e) {
|
||||
errorSystem.show('界面更新失败: ' + e.message);
|
||||
}
|
||||
}
|
||||
|
||||
// 新增:格式化时间显示函数
|
||||
function formatTime(ms) {
|
||||
try {
|
||||
if (ms < 0) return '00:00';
|
||||
var totalSeconds = Math.floor(ms / 1000),
|
||||
minutes = Math.floor(totalSeconds / 60),
|
||||
seconds = totalSeconds % 60;
|
||||
return (minutes < 10 ? '0' : '') + minutes + ':' + (seconds < 10 ? '0' : '') + seconds;
|
||||
} catch (e) {
|
||||
return '--:--';
|
||||
}
|
||||
}
|
||||
|
||||
// 新增:更新课程表显示
|
||||
function updateScheduleTable() {
|
||||
try {
|
||||
var now = new Date(),
|
||||
rows = document.querySelectorAll('#scheduleTable tr:not(:first-child)');
|
||||
for (var i = 0; i < rows.length; i++) {
|
||||
var course = courseSchedule[i],
|
||||
start = parseTime(course.start),
|
||||
end = parseTime(course.end),
|
||||
row = rows[i];
|
||||
row.className = '';
|
||||
if (now >= start && now <= end) {
|
||||
row.className = 'current-class';
|
||||
} else if (now < start) {
|
||||
row.className = 'future-class';
|
||||
} else {
|
||||
row.className = 'past-class';
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
errorSystem.show('课程表更新失败: ' + e.message);
|
||||
}
|
||||
}
|
||||
|
||||
// 新增:获取下一节课
|
||||
function getNextCourse() {
|
||||
try {
|
||||
var now = new Date();
|
||||
for (var i = 0; i < courseSchedule.length; i++) {
|
||||
var start = parseTime(courseSchedule[i].start);
|
||||
if (start > now) return courseSchedule[i];
|
||||
}
|
||||
return null;
|
||||
} catch (e) {
|
||||
errorSystem.show('获取下一节课失败: ' + e.message);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// 修改:全屏切换函数
|
||||
function toggleFullscreen() {
|
||||
try {
|
||||
isFullscreen = !isFullscreen;
|
||||
document.body.classList.toggle('fullscreen-mode', isFullscreen);
|
||||
if (isFullscreen) {
|
||||
document.querySelector('.settings-panel').style.display = 'none';
|
||||
document.querySelector('.schedule-table').style.display = 'none';
|
||||
document.querySelector('.container').style.width = '100%';
|
||||
document.querySelector('.container').style.height = '100%';
|
||||
} else {
|
||||
document.querySelector('.settings-panel').style.display = '';
|
||||
document.querySelector('.schedule-table').style.display = '';
|
||||
document.querySelector('.container').style.width = '';
|
||||
document.querySelector('.container').style.height = '';
|
||||
}
|
||||
} catch (e) {
|
||||
errorSystem.show('全屏切换失败: ' + e.message);
|
||||
}
|
||||
}
|
||||
|
||||
// 测试铃声函数中调用音频播放改用 audioController
|
||||
function testSound(type) {
|
||||
try {
|
||||
if (confirm('确定要测试' + (type === 'classStart' ? '上课' : '下课') + '铃声吗?')) {
|
||||
audioController.play(type);
|
||||
}
|
||||
} catch (e) {
|
||||
errorSystem.show('测试铃声失败: ' + e.message);
|
||||
}
|
||||
}
|
||||
|
||||
// 修改:系统初始化函数
|
||||
function init() {
|
||||
try {
|
||||
var table = document.getElementById('scheduleTable');
|
||||
courseSchedule.forEach(function(course) {
|
||||
var row = table.insertRow(-1);
|
||||
row.innerHTML = '<td>' + course.name + '</td>' +
|
||||
'<td>' + course.start + ' - ' + course.end + '</td>' +
|
||||
'<td></td>';
|
||||
});
|
||||
// 初始化设置复选框
|
||||
document.getElementById('classBell').checked = localStorage.classBell === 'true';
|
||||
document.getElementById('breakBell').checked = localStorage.breakBell === 'true';
|
||||
document.getElementById('classBell').onchange = function () {
|
||||
localStorage.classBell = this.checked;
|
||||
};
|
||||
document.getElementById('breakBell').onchange = function () {
|
||||
localStorage.breakBell = this.checked;
|
||||
};
|
||||
// 启动安全更新循环
|
||||
safeUpdate();
|
||||
// 移除或修改音频权限激活代码(用原音频系统无需特殊激活)
|
||||
document.body.onclick = null;
|
||||
} catch (e) {
|
||||
errorSystem.show('系统初始化失败: ' + e.message);
|
||||
}
|
||||
}
|
||||
window.onbeforeunload = function () {
|
||||
if (timer) clearTimeout(timer);
|
||||
};
|
||||
init();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -38,27 +38,29 @@
|
||||
padding: 20px;
|
||||
background: url('../background.jpg') no-repeat center center fixed;
|
||||
background-size: cover;
|
||||
color: #2d3436;
|
||||
color: #ecf0f1;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 100vh;
|
||||
background-color: #2c3e50;
|
||||
}
|
||||
|
||||
.container {
|
||||
text-align: center;
|
||||
background: rgba(255, 255, 255, 0.8);
|
||||
border: 1px solid #e0e6ed;
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
border: 1px solid rgba(255, 255, 255, 0.2);
|
||||
padding: 30px;
|
||||
border-radius: 16px;
|
||||
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.06);
|
||||
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.2);
|
||||
backdrop-filter: blur(10px);
|
||||
animation: fadeIn 2s ease-in-out;
|
||||
}
|
||||
|
||||
.time {
|
||||
font-size: 10rem;
|
||||
margin: 0;
|
||||
color: #2c3e50;
|
||||
color: #ecf0f1;
|
||||
font-weight: 700;
|
||||
text-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||
animation: glow 1s ease-in-out infinite alternate;
|
||||
@ -67,7 +69,7 @@
|
||||
.text {
|
||||
font-size: 1.5rem;
|
||||
margin-bottom: 20px;
|
||||
color: #57606f;
|
||||
color: #bdc3c7;
|
||||
}
|
||||
|
||||
.btn {
|
||||
@ -93,7 +95,7 @@
|
||||
}
|
||||
|
||||
.btn.fullscreen {
|
||||
background-color: #f44336;
|
||||
background: linear-gradient(135deg, #e74c3c, #c0392b);
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user