<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>学校时间表 - 上下排列优化版</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Segoe UI', 'Microsoft YaHei', sans-serif;
}
body {
background: linear-gradient(135deg, #1a2a6c, #b21f1f, #fdbb2d);
color: #333;
padding: 20px;
min-height: 100vh;
}
.container {
max-width: 1200px;
margin: 0 auto;
background: rgba(255, 255, 255, 0.97);
padding: 30px;
border-radius: 15px;
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.3);
}
.header {
text-align: center;
margin-bottom: 30px;
padding-bottom: 25px;
border-bottom: 3px solid #f0f3f8;
}
h1 {
color: #2c3e50;
font-size: 2.8rem;
margin-bottom: 15px;
background: linear-gradient(45deg, #1a2a6c, #b21f1f);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
padding: 10px 0;
}
.subtitle {
color: #7f8c8d;
font-size: 1.3rem;
margin-bottom: 20px;
}
.timelines-container {
display: flex;
flex-direction: column;
gap: 40px;
margin-bottom: 30px;
}
.timeline-section {
background: #f8fafc;
padding: 25px;
border-radius: 15px;
box-shadow: 0 8px 25px rgba(0,0,0,0.1);
position: relative;
overflow: hidden;
}
.timeline-section::before {
content: "";
position: absolute;
top: 0;
left: 0;
width: 6px;
height: 100%;
}
.morning-section::before {
background: linear-gradient(to bottom, #3498db, #2c3e50);
}
.afternoon-section::before {
background: linear-gradient(to bottom, #e67e22, #d35400);
}
.evening-section::before {
background: linear-gradient(to bottom, #9b59b6, #8e44ad);
}
.section-title {
font-size: 1.8rem;
font-weight: bold;
color: #2c3e50;
margin-bottom: 25px;
padding-left: 20px;
display: flex;
align-items: center;
gap: 15px;
}
.section-title i {
font-size: 1.8rem;
}
.morning-section .section-title i {
color: #3498db;
}
.afternoon-section .section-title i {
color: #e67e22;
}
.evening-section .section-title i {
color: #9b59b6;
}
.timeline-row {
position: relative;
height: 180px;
margin: 20px 0;
background: linear-gradient(to right, #f8f9fa, #e9ecef);
border-radius: 12px;
overflow: visible;
border: 1px solid #e0e6ed;
}
.time-marker {
position: absolute;
height: 100%;
width: 1px;
background-color: #ced4da;
top: 0;
z-index: 1;
}
.hour-label {
position: absolute;
top: -35px;
transform: translateX(-50%);
font-size: 1.1rem;
color: #495057;
background-color: #f8f9fa;
padding: 5px 15px;
border-radius: 20px;
z-index: 2;
box-shadow: 0 3px 10px rgba(0,0,0,0.08);
border: 1px solid #e0e6ed;
font-weight: 600;
}
.time-block {
position: absolute;
height: 140px;
top: 20px;
border-radius: 10px;
z-index: 3;
transition: all 0.3s ease;
box-shadow: 0 5px 15px rgba(0,0,0,0.12);
cursor: pointer;
overflow: hidden;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
padding: 10px;
text-align: center;
}
.time-block:hover {
transform: translateY(-5px);
box-shadow: 0 8px 20px rgba(0,0,0,0.2);
z-index: 5;
}
.time-block-label {
font-size: 1.2rem;
font-weight: bold;
color: white;
margin-bottom: 8px;
text-shadow: 0 1px 3px rgba(0,0,0,0.3);
z-index: 4;
}
.time-block-time {
font-size: 1.1rem;
color: rgba(255,255,255,0.95);
font-weight: 500;
z-index: 4;
background: rgba(0,0,0,0.1);
padding: 5px 15px;
border-radius: 15px;
}
.current-time {
position: absolute;
top: 0;
width: 3px;
height: 180px;
background: linear-gradient(to bottom, transparent, #e74c3c, transparent);
z-index: 10;
}
.current-time-dot {
position: absolute;
top: 0;
left: -8px;
width: 16px;
height: 16px;
background-color: #e74c3c;
border-radius: 50%;
box-shadow: 0 0 0 5px rgba(231, 76, 60, 0.3);
animation: pulse 2s infinite;
z-index: 11;
}
.current-time-label {
position: absolute;
top: 185px;
left: -45px;
width: 90px;
text-align: center;
font-size: 1.1rem;
font-weight: bold;
color: white;
background: #e74c3c;
padding: 6px;
border-radius: 20px;
box-shadow: 0 4px 15px rgba(0,0,0,0.2);
z-index: 11;
}
.legend {
display: flex;
justify-content: center;
margin: 40px 0 30px;
gap: 25px;
flex-wrap: wrap;
}
.legend-item {
display: flex;
align-items: center;
font-size: 1.2rem;
background-color: #f8f9fa;
padding: 10px 25px;
border-radius: 30px;
box-shadow: 0 3px 10px rgba(0,0,0,0.1);
transition: transform 0.3s;
}
.legend-item:hover {
transform: translateY(-5px);
box-shadow: 0 5px 15px rgba(0,0,0,0.15);
}
.legend-color {
width: 20px;
height: 20px;
margin-right: 12px;
border-radius: 50%;
box-shadow: 0 2px 6px rgba(0,0,0,0.2);
}
.footer-note {
text-align: center;
margin-top: 30px;
font-size: 1.1rem;
color: #6c757d;
padding: 15px;
background: #f8f9fa;
border-radius: 15px;
box-shadow: 0 3px 10px rgba(0,0,0,0.08);
display: flex;
justify-content: center;
align-items: center;
gap: 10px;
}
.time-tooltip {
position: absolute;
background: rgba(0, 0, 0, 0.85);
color: white;
padding: 10px 20px;
border-radius: 10px;
font-size: 1.1rem;
z-index: 100;
pointer-events: none;
transform: translateX(-50%);
box-shadow: 0 5px 15px rgba(0,0,0,0.2);
white-space: nowrap;
display: none;
font-weight: 500;
}
.schedule-title {
text-align: center;
margin: 30px 0;
color: #2c3e50;
font-size: 1.5rem;
background: rgba(255,255,255,0.7);
padding: 15px;
border-radius: 15px;
box-shadow: 0 4px 12px rgba(0,0,0,0.1);
}
@keyframes pulse {
0% { box-shadow: 0 0 0 0 rgba(231, 76, 60, 0.5); }
70% { box-shadow: 0 0 0 12px rgba(231, 76, 60, 0); }
100% { box-shadow: 0 0 0 0 rgba(231, 76, 60, 0); }
}
.info-bar {
display: flex;
justify-content: center;
gap: 30px;
margin: 20px 0;
flex-wrap: wrap;
}
.info-item {
display: flex;
align-items: center;
gap: 10px;
font-size: 1.1rem;
background: #f0f7ff;
padding: 10px 20px;
border-radius: 30px;
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
}
</style>
</head>
<body>
<div class="container">
<div class="header">
<h1><i class="fas fa-school"></i> 学校作息时间表</h1>
<div class="subtitle">优化版 - 上下排列布局,时间轴更宽裕</div>
</div>
<div class="info-bar">
<div class="info-item">
<i class="fas fa-clock"></i>
<span>当前时间: <span id="current-time-display">--:--:--</span></span>
</div>
<div class="info-item">
<i class="fas fa-calendar-alt"></i>
<span>2023-2024学年 上学期</span>
</div>
<div class="info-item">
<i class="fas fa-sync-alt"></i>
<span>最后更新: <span id="update-time"></span></span>
</div>
</div>
<div class="timelines-container">
<!-- 上午时段 -->
<div class="timeline-section morning-section">
<div class="section-title">
<i class="fas fa-sun"></i>
上午时段 (6:55 - 11:55)
</div>
<div class="timeline-row" id="morning-timeline"></div>
</div>
<!-- 下午时段 -->
<div class="timeline-section afternoon-section">
<div class="section-title">
<i class="fas fa-cloud-sun"></i>
下午时段 (13:00 - 17:50)
</div>
<div class="timeline-row" id="afternoon-timeline"></div>
</div>
<!-- 晚上时段 -->
<div class="timeline-section evening-section">
<div class="section-title">
<i class="fas fa-moon"></i>
晚上时段 (18:30 - 21:25)
</div>
<div class="timeline-row" id="evening-timeline"></div>
</div>
</div>
<div class="legend">
<div class="legend-item">
<div class="legend-color" style="background: #27ae60;"></div>
<span>课程/自习</span>
</div>
<div class="legend-item">
<div class="legend-color" style="background: #e67e22;"></div>
<span>休息/就餐</span>
</div>
<div class="legend-item">
<div class="legend-color" style="background: #3498db;"></div>
<span>活动/运动</span>
</div>
<div class="legend-item">
<div class="legend-color" style="background: #9b59b6;"></div>
<span>眼保健操</span>
</div>
<div class="legend-item">
<div class="legend-color" style="background: #e74c3c;"></div>
<span>当前时间</span>
</div>
</div>
<div class="footer-note">
<i class="fas fa-info-circle"></i>
时间轴已优化 | 上下排列布局 | 当前时间精确显示 | 最后更新时间: <span id="update-time-footer"></span>
</div>
</div>
<script>
// 时间表数据 - 分开上午、下午和晚上
const morningSchedule = [
{ name: "早自习", start: "6:55", end: "7:30", type: "study" },
{ name: "早餐", start: "7:30", end: "7:50", type: "break" },
{ name: "第1节", start: "7:50", end: "8:30", type: "study" },
{ name: "跑操", start: "8:30", end: "8:50", type: "activity" },
{ name: "第2节", start: "8:50", end: "9:30", type: "study" },
{ name: "第3节", start: "9:40", end: "10:20", type: "study" },
{ name: "第4节", start: "10:30", end: "11:10", type: "study" },
{ name: "第5节", start: "11:20", end: "11:55", type: "study" }
];
const afternoonSchedule = [
{ name: "午休", start: "13:00", end: "13:50", type: "break" },
{ name: "第6节", start: "14:00", end: "14:40", type: "study" },
{ name: "第7节", start: "14:50", end: "15:30", type: "study" },
{ name: "眼保健操", start: "15:30", end: "15:45", type: "eye" },
{ name: "第8节", start: "15:45", end: "16:30", type: "study" },
{ name: "第9节", start: "16:40", end: "17:20", type: "study" },
{ name: "听力晚读", start: "17:25", end: "17:50", type: "activity" }
];
const eveningSchedule = [
{ name: "晚餐", start: "17:50", end: "18:20", type: "break" },
{ name: "晚1节", start: "18:30", end: "19:10", type: "study" },
{ name: "晚2节", start: "19:20", end: "20:00", type: "study" },
{ name: "晚3节", start: "20:10", end: "20:50", type: "study" },
{ name: "晚4节", start: "20:55", end: "21:25", type: "study" }
];
// 时间区块颜色
const colors = {
study: "#27ae60",
break: "#e67e22",
activity: "#3498db",
eye: "#9b59b6"
};
// 初始化时间轴
function initTimeline(timelineId, schedule, startHour, endHour) {
const timeline = document.getElementById(timelineId);
const fullWidth = timeline.offsetWidth;
const totalMinutes = (endHour - startHour) * 60;
// 清空时间轴
timeline.innerHTML = '';
// 添加时间提示工具
const timeTooltip = document.createElement('div');
timeTooltip.className = 'time-tooltip';
timeTooltip.id = timelineId + '-tooltip';
timeline.appendChild(timeTooltip);
// 添加小时刻度
for (let hour = startHour; hour <= endHour; hour++) {
const minutesFromStart = (hour - startHour) * 60;
const left = (minutesFromStart / totalMinutes) * fullWidth;
const marker = document.createElement('div');
marker.className = 'time-marker';
marker.style.left = `${left}px`;
const label = document.createElement('div');
label.className = 'hour-label';
label.style.left = `${left}px`;
label.textContent = `${hour}:00`;
timeline.appendChild(marker);
timeline.appendChild(label);
}
// 添加时间段区块
schedule.forEach(item => {
const [startH, startM] = item.start.split(':').map(Number);
const [endH, endM] = item.end.split(':').map(Number);
// 计算相对于时间轴开始的时间位置(分钟)
const absStart = (startH - startHour) * 60 + startM;
const absEnd = (endH - startHour) * 60 + endM;
// 计算像素位置和宽度
const left = (absStart / totalMinutes) * fullWidth;
const width = ((absEnd - absStart) / totalMinutes) * fullWidth;
// 确保最小宽度
if (width >= 15) {
const block = document.createElement('div');
block.className = 'time-block';
block.style.left = `${left}px`;
block.style.width = `${width}px`;
block.style.backgroundColor = colors[item.type];
// 添加主标签
const label = document.createElement('div');
label.className = 'time-block-label';
label.textContent = item.name;
// 添加时间标签
const timeLabel = document.createElement('div');
timeLabel.className = 'time-block-time';
timeLabel.textContent = `${item.start} - ${item.end}`;
block.appendChild(label);
block.appendChild(timeLabel);
timeline.appendChild(block);
// 添加鼠标悬停事件
block.addEventListener('mousemove', (e) => {
const rect = timeline.getBoundingClientRect();
const x = e.clientX - rect.left;
const percent = x / fullWidth;
const totalMins = percent * totalMinutes;
const hours = startHour + Math.floor(totalMins / 60);
const minutes = Math.floor(totalMins % 60);
const timeString = `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}`;
timeTooltip.textContent = timeString;
timeTooltip.style.left = `${x}px`;
timeTooltip.style.top = `-50px`;
timeTooltip.style.display = 'block';
});
block.addEventListener('mouseleave', () => {
timeTooltip.style.display = 'none';
});
}
});
// 添加当前时间指示器
const currentTime = document.createElement('div');
currentTime.className = 'current-time';
const dot = document.createElement('div');
dot.className = 'current-time-dot';
const label = document.createElement('div');
label.className = 'current-time-label';
currentTime.appendChild(dot);
currentTime.appendChild(label);
timeline.appendChild(currentTime);
// 添加时间轴鼠标移动事件
timeline.addEventListener('mousemove', (e) => {
const rect = timeline.getBoundingClientRect();
const x = e.clientX - rect.left;
const percent = x / fullWidth;
const totalMins = percent * totalMinutes;
const hours = startHour + Math.floor(totalMins / 60);
const minutes = Math.floor(totalMins % 60);
const timeString = `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}`;
timeTooltip.textContent = timeString;
timeTooltip.style.left = `${x}px`;
timeTooltip.style.top = `-50px`;
timeTooltip.style.display = 'block';
});
timeline.addEventListener('mouseleave', () => {
timeTooltip.style.display = 'none';
});
return {
element: timeline,
currentTime,
currentLabel: label,
startHour,
endHour,
totalMinutes,
fullWidth
};
}
// 初始化时间轴
const morning = initTimeline('morning-timeline', morningSchedule, 6, 12);
const afternoon = initTimeline('afternoon-timeline', afternoonSchedule, 13, 18);
const evening = initTimeline('evening-timeline', eveningSchedule, 18, 22);
// 更新当前时间
function updateCurrentTime() {
const now = new Date();
const hours = now.getHours();
const minutes = now.getMinutes();
const seconds = now.getSeconds();
const timeString = `${hours.toString().padStart(2,'0')}:${minutes.toString().padStart(2,'0')}:${seconds.toString().padStart(2,'0')}`;
// 更新最后更新时间显示
document.getElementById('update-time').textContent = now.toLocaleString();
document.getElementById('update-time-footer').textContent = now.toLocaleString();
document.getElementById('current-time-display').textContent = timeString;
// 更新上午时间轴
if (hours >= morning.startHour && hours < morning.endHour) {
const elapsed = ((hours - morning.startHour) * 3600 + minutes * 60 + seconds) / 60;
const left = (elapsed / morning.totalMinutes) * morning.fullWidth;
morning.currentTime.style.left = `${Math.max(0, Math.min(left, morning.fullWidth))}px`;
morning.currentLabel.textContent = timeString;
morning.currentTime.style.display = 'block';
} else {
morning.currentTime.style.display = 'none';
}
// 更新下午时间轴
if (hours >= afternoon.startHour && hours < afternoon.endHour) {
const elapsed = ((hours - afternoon.startHour) * 3600 + minutes * 60 + seconds) / 60;
const left = (elapsed / afternoon.totalMinutes) * afternoon.fullWidth;
afternoon.currentTime.style.left = `${Math.max(0, Math.min(left, afternoon.fullWidth))}px`;
afternoon.currentLabel.textContent = timeString;
afternoon.currentTime.style.display = 'block';
} else {
afternoon.currentTime.style.display = 'none';
}
// 更新晚上时间轴
if (hours >= evening.startHour && hours < evening.endHour) {
const elapsed = ((hours - evening.startHour) * 3600 + minutes * 60 + seconds) / 60;
const left = (elapsed / evening.totalMinutes) * evening.fullWidth;
evening.currentTime.style.left = `${Math.max(0, Math.min(left, evening.fullWidth))}px`;
evening.currentLabel.textContent = timeString;
evening.currentTime.style.display = 'block';
} else {
evening.currentTime.style.display = 'none';
}
}
// 初始更新
updateCurrentTime();
// 每秒更新60次实现平滑动画
setInterval(updateCurrentTime, 1000/60);
// 窗口大小变化时重新计算
window.addEventListener('resize', () => {
initTimeline('morning-timeline', morningSchedule, 6, 12);
initTimeline('afternoon-timeline', afternoonSchedule, 13, 18);
initTimeline('evening-timeline', eveningSchedule, 18, 22);
updateCurrentTime();
});
</script>
</body>
</html>