class / templates /student.html
ikun520's picture
Update templates/student.html
aa3d277 verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>教师课表</title>
<style>
/* 全局样式 */
body {
font-family: 'Roboto', Arial, sans-serif;
margin: 0;
padding: 0;
background-color: #f4f6f9;
color: #333;
}
h1 {
text-align: center;
margin: 20px 0;
font-size: 28px;
font-weight: bold;
color: #0078d4;
letter-spacing: 1.2px;
}
/* 控制区域样式 */
.controls {
display: flex;
justify-content: space-between;
align-items: center;
padding: 15px 20px;
background-color: #0078d4;
color: white;
border-radius: 10px;
margin: 10px 20px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
}
.controls > div {
flex: 1; /* 让每个子元素均匀分布 */
text-align: center; /* 居中对齐子元素 */
}
.nav-button {
padding: 10px 15px;
font-size: 14px;
border: none;
border-radius: 5px;
background-color: #fff;
color: #0078d4;
font-weight: bold;
cursor: pointer;
transition: all 0.3s ease;
}
.nav-button:hover {
background-color: #eaf4fc;
}
.nav-button:focus {
outline: none;
box-shadow: 0 0 5px rgba(0, 120, 212, 0.8);
}
.controls label {
font-weight: bold;
margin-right: 10px;
}
.controls select, .controls button {
padding: 8px 12px;
font-size: 14px;
border: none;
border-radius: 5px;
background-color: #fff;
color: #0078d4;
font-weight: bold;
cursor: pointer;
transition: all 0.3s ease;
}
.controls select:hover, .controls button:hover {
background-color: #eaf4fc;
}
.controls select:focus, .controls button:focus {
outline: none;
box-shadow: 0 0 5px rgba(0, 120, 212, 0.8);
}
/* 时间表头样式 */
.time-header {
display: grid;
grid-template-columns: 70px repeat(7, 1fr);
background: linear-gradient(135deg, #0078d4 0%, #0056a6 100%);
color: white;
text-align: center;
margin: 10px 20px;
font-size: 14px;
font-weight: bold;
padding: 10px 0;
border-radius: 8px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}
.time-header div {
border-right: 1px solid #f0f0f0;
padding: 5px;
transition: transform 0.2s ease-in-out, background-color 0.2s; /* 添加平滑过渡效果 */
}
.time-header div:last-child {
border-right: none;
}
/* 鼠标悬停时样式 */
.time-header div:hover {
transform: translateY(-2px); /* 轻微上移 */
background-color: rgba(255, 255, 255, 0.2); /* 悬停背景高亮 */
cursor: pointer; /* 鼠标样式 */
}
/* 时间列样式 */
.time-column {
background-color: #f8f9fa;
text-align: center;
font-size: 14px;
display: flex;
flex-direction: column;
border-right: 1px solid #ddd;
}
.time-column div {
flex: 1;
padding: 10px 0;
border-top: 1px solid #ddd;
font-weight: bold;
}
.time-column div:first-child {
border-top: none;
}
/* 每日课程样式 */
.day {
background-color: white;
border: 1px solid #ddd;
padding: 5px;
height: 500px;
display: flex;
flex-direction: column;
position: relative;
border-radius: 0 0 8px 8px;
overflow: hidden;
transition: transform 0.3s ease, box-shadow 0.3s ease;
}
.day:hover {
transform: translateY(-5px);
box-shadow: 0 8px 15px rgba(0, 0, 0, 0.15);
}
/* 时间槽样式 */
.time-slot {
flex: 1;
position: relative;
border-top: 1px solid #eee;
overflow: hidden;
}
.time-slot:first-child {
border-top: none;
}
/* 课程样式 */
.time-slot .course {
position: absolute;
background-color: #a7d8de;
color: #333;
border-radius: 5px;
padding: 25px;
font-size: 15px;
font-weight: bold;
text-align: center;
margin: 5px;
width: 75%; /* 调整宽度为95% */
/*right: 2%; !* 调整位置,让它靠左边一些 *!*/
box-shadow: 2px 4px 8px rgba(0, 0, 0, 0.1);
transition: transform 0.3s ease, background-color 0.3s ease;
height: 50%;
}
.search-container {
position: relative; /* 使搜索结果相对搜索框定位 */
}
.teacher-search {
width: 150px; /* 搜索框固定宽度 */
padding: 8px 12px;
font-size: 14px;
border: 1px solid #0078d4; /* 蓝色边框 */
border-radius: 5px;
color: #333;
box-sizing: border-box; /* 确保宽度包含内边距和边框 */
}
.search-results {
position: absolute; /* 使结果相对于搜索框容器定位 */
top: calc(100% + 4px); /* 紧贴搜索框下方,并增加 4px 间距 */
left: 42.5%; /* 确保左对齐 */
width: 150px; /* 与搜索框宽度一致 */
background: #f0f8ff; /* 浅蓝背景 */
border: 1px solid #0078d4; /* 与搜索框相同的蓝色边框 */
max-height: 150px; /* 最大高度 */
overflow-y: auto; /* 启用滚动条 */
z-index: 1000; /* 确保结果在顶层显示 */
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); /* 增加阴影 */
border-radius: 5px; /* 与搜索框一致的圆角 */
}
.search-results div {
padding: 8px 12px; /* 每个选项的内边距 */
font-size: 14px; /* 字体大小 */
color: #333; /* 默认文字颜色 */
cursor: pointer; /* 鼠标悬停时显示为手型 */
transition: background 0.3s, color 0.3s; /* 添加平滑过渡效果 */
}
.search-results div:hover {
background-color: #0078d4; /* 鼠标悬停时背景色 */
color: #fff; /* 悬停时文字颜色 */
}
/* 网格容器样式 */
.schedule-container {
display: grid;
grid-template-columns: 70px repeat(7, 1fr);
gap: 2px;
margin: 10px 20px;
background-color: #fff;
border-radius: 10px;
overflow: hidden;
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
}
@media (max-width: 768px) {
body {
font-size: 14px;
padding: 5px;
}
h1 {
font-size: 20px;
margin: 15px 0;
}
.controls {
display: flex;
flex-direction: row; /* 保持在一行内 */
flex-wrap: nowrap; /* 禁止换行 */
justify-content: space-around; /* 均匀分布各个控件 */
align-items: center; /* 纵向居中 */
padding: 10px 5px; /* 增加一些内边距,使其不显得太拥挤 */
margin: 5px;
gap: 5px; /* 控制组件之间的间距 */
}
.controls select,
.controls button {
padding: 6px; /* 适当减少内边距以适应小屏幕 */
font-size: 12px; /* 调整字体大小适应小屏幕 */
margin: 2px;
min-width: 80px; /* 设置最小宽度,确保控件在小屏幕上仍可点击 */
}
.time-header {
grid-template-columns: 25px repeat(7, 1fr);
font-size: 12px; /* 调整字体大小以适合移动端 */
padding: 12px 5px; /* 增加上下的内边距使其看起来更高 */
width: 95%;
margin: 10px 5px;
}
.schedule-container {
grid-template-columns: 22px repeat(7, minmax(0, 1fr));
margin: 3px;
display: grid;
gap: 1px;
background-color: #fff;
border-radius: 10px;
overflow: hidden;
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
}
.day {
padding: 3px;
border: 1px solid #ccc;
border-radius: 5px;
}
.time-column {
grid-column: 1;
text-align: center;
font-size: 15px;
display: flex;
flex-direction: column;
justify-content: center;
line-height: 1.2;
}
.time-slot .course {
font-size: 12px;
padding: 1px;
/*height: auto;*/
width: auto;
word-break: break-word; /* 确保长单词在小屏幕上也会换行 */
white-space: normal; /* 允许文本换行 */
overflow-wrap: break-word; /* 处理可能过长的文本,强制其换行 */
margin: 1px;
height: 90%;
}
.teacher-search {
width: 100%; /* 搜索框固定宽度 */
padding: 8px 12px;
font-size: 14px;
border: 1px solid #0078d4; /* 蓝色边框 */
border-radius: 5px;
color: #333;
box-sizing: border-box; /* 确保宽度包含内边距和边框 */
}
.search-results {
position: absolute;
top: calc(100% + 2px); /* 列表紧贴搜索框下方,留 2px 的间隙 */
left: 0%; /* 与搜索框左侧完全对齐 */
width: 100%; /* 列表宽度与搜索框保持一致 */
background: #f0f8ff; /* 浅蓝背景 */
border: 1px solid #0078d4; /* 边框颜色 */
max-height: 150px; /* 最大高度,超出部分滚动 */
overflow-y: auto; /* 启用垂直滚动条 */
z-index: 1000; /* 确保显示在最上层 */
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); /* 添加阴影效果 */
border-radius: 5px; /* 圆角边框 */
box-sizing: border-box; /* 确保宽度计算准确 */
}
}
</style>
</head>
<body>
<h1>学生课表</h1>
<div class="controls">
<div class="search-container">
<label for="teacher-search">学生:</label>
<input type="text" id="teacher-search" class="teacher-search" placeholder="搜索学生名字">
<div id="search-results" class="search-results"></div>
</div>
<div>
<button class="nav-button" onclick="navigateToSection_01()">班级查询</button>
<button class="nav-button" onclick="navigateToSection_02()">教师查询</button>
</div>
<div>
<label for="week-select">周次:</label>
<select id="week-select"></select>
</div>
</div>
<div class="time-header" id="time-header">
<div>时间</div>
<div>周一</div>
<div>周二</div>
<div>周三</div>
<div>周四</div>
<div>周五</div>
<div>周六</div>
<div>周日</div>
</div>
<div class="schedule-container" id="schedule">
<div class="time-column">
<div>1-3节</div>
<div>4-5节</div>
<div>6-8节</div>
<div>9-11节</div>
</div>
</div>
<script>
let currentWeek = getCurrentWeek(); // 使用 getCurrentWeek() 函数获取当前周次
let teacherList = [];
function initializeWeeks() {
const weekSelect = document.getElementById("week-select");
for (let i = 1; i <= 18; i++) {
const option = document.createElement("option");
option.value = i;
option.textContent = `第${i}周`;
if (i === currentWeek) {
option.selected = true; // 默认选中当前周次
}
weekSelect.appendChild(option);
}
}
function getCurrentWeek() {
const firstWeekStartDate = new Date("2024-09-02"); // 假设第一周从2024年9月2日(周一)开始
const today = new Date();
const timeDifference = today - firstWeekStartDate;
const daysDifference = Math.floor(timeDifference / (1000 * 60 * 60 * 24));
return Math.floor(daysDifference / 7) + 1; // 根据天数计算当前周次
}
function loadTeachers() {
fetch("/api/students")
.then(response => response.json())
.then(teachers => {
teacherList = teachers.sort((a, b) => {
if (a === "秦振凯") return -1;
if (b === "秦振凯") return 1;
return a.localeCompare(b);
});
})
.catch(error => console.error("加载学生列表出错:", error));
}
function searchTeachers() {
const searchInput = document.getElementById("teacher-search").value.toLowerCase();
const searchResults = document.getElementById("search-results");
searchResults.innerHTML = "";
if (searchInput.trim() === "") {
return;
}
const filteredTeachers = teacherList.filter(teacher =>
teacher.toLowerCase().includes(searchInput)
);
filteredTeachers.forEach(teacher => {
const resultDiv = document.createElement("div");
resultDiv.textContent = teacher;
resultDiv.onclick = () => selectTeacher(teacher);
searchResults.appendChild(resultDiv);
});
}
function selectTeacher(teacher) {
document.getElementById("teacher-search").value = teacher;
document.getElementById("search-results").innerHTML = "";
loadSchedule();
}
function loadSchedule() {
const teacherSearch = document.getElementById("teacher-search").value;
const weekSelect = document.getElementById("week-select");
const selectedWeek = parseInt(weekSelect.value);
const apiUrl = `/api/student_courses_v2?week=${selectedWeek}&student_name=${encodeURIComponent(teacherSearch)}`;
// 先清空之前的表头和课程表内容,避免混淆
document.getElementById("time-header").innerHTML = '';
document.getElementById("schedule").innerHTML = `
<div class='time-column'>
<div>1-3节</div>
<div>4-5节</div>
<div>6-8节</div>
<div>9-11节</div>
</div>
`;
// 获取所选周次的起始日期
const firstWeekStartDate = new Date("2024-09-02"); // 假设第一周从2024年9月2日(周一)开始
const selectedWeekStartDate = new Date(firstWeekStartDate);
selectedWeekStartDate.setDate(firstWeekStartDate.getDate() + (selectedWeek - 1) * 7);
// 更新时间表头
updateTimeHeader(selectedWeekStartDate);
fetch(apiUrl)
.then(response => response.json())
.then(data => {
if (data.length === 0) {
console.warn("未获取到课程数据");
return;
}
// 初始化空白课程表
const groupedByDay = Array.from({ length: 7 }, () => ({
intervals: Array.from({ length: 4 }, () => [])
}));
// 填充课程
data.forEach(course => {
const dayIndex = course.星期 - 1; // 星期一为0,星期日为6
const startPeriod = course.节次[0];
let intervalIndex = 0;
if (startPeriod >= 1 && startPeriod <= 3) intervalIndex = 0;
else if (startPeriod >= 4 && startPeriod <= 5) intervalIndex = 1;
else if (startPeriod >= 6 && startPeriod <= 8) intervalIndex = 2;
else if (startPeriod >= 9 && startPeriod <= 11) intervalIndex = 3;
groupedByDay[dayIndex].intervals[intervalIndex].push(course);
});
// 渲染课程表
const scheduleContainer = document.getElementById("schedule");
groupedByDay.forEach((dayData, dayIndex) => {
const dayDiv = document.createElement("div");
dayDiv.className = "day";
dayData.intervals.forEach((intervalCourses, intervalIndex) => {
const intervalDiv = document.createElement("div");
intervalDiv.className = "time-slot";
if (intervalCourses.length > 0) {
const course = intervalCourses[0];
const courseDiv = document.createElement("div");
courseDiv.className = "course";
courseDiv.innerText = `${course.课程} ${course.地点}`;
courseDiv.style.backgroundColor = randomColor();
intervalDiv.appendChild(courseDiv);
}
dayDiv.appendChild(intervalDiv);
});
scheduleContainer.appendChild(dayDiv);
});
})
.catch(error => console.error("加载课程表出错:", error));
}
function updateTimeHeader(weekStartDate) {
const timeHeader = document.getElementById("time-header");
const weekDates = generateWeekDates(weekStartDate);
// 清空表头后重新生成
timeHeader.innerHTML = `
<div>时间</div>
`;
weekDates.forEach((date, index) => {
const dayOfWeek = "一二三四五六日"[index];
const formattedDate = date.toLocaleDateString("zh-CN", { month: "2-digit", day: "2-digit" });
const headerDiv = document.createElement("div");
headerDiv.innerHTML = `
<span>${formattedDate}</span>
<br />
<span>周${dayOfWeek}</span>
`;
timeHeader.appendChild(headerDiv);
});
}
function generateWeekDates(startDate) {
const dates = [];
for (let i = 0; i < 7; i++) {
const date = new Date(startDate);
date.setDate(date.getDate() + i);
dates.push(date);
}
return dates;
}
function navigateToSection_01() {
window.location.href = "/";
}
function navigateToSection_02() {
window.location.href = "/teachers";
}
function randomColor() {
const colors = ["#ffcccb", "#c6e2ff", "#d5f5e3", "#f7dc6f", "#f1948a", "#aed6f1", "#d7bde2"];
return colors[Math.floor(Math.random() * colors.length)];
}
document.getElementById("week-select").addEventListener("change", loadSchedule);
document.getElementById("teacher-search").addEventListener("input", searchTeachers);
initializeWeeks();
loadTeachers();
</script>
</body>
</html>