评论

收藏

[Html/CSS] html+JS写的一个可拖拽课程表

开发技术 开发技术 发布于:2025-07-20 15:49 | 阅读数:12 | 评论:0

来自吾爱论坛大神的杰作

Snipaste_2025-07-20_15-59-03.png

html代码:
<!DOCTYPE html>
<html lang="zh-CN">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>拖拽定制课程表</title>
  <style>
    body {
      font-family: Arial, sans-serif;
      margin: 0 5%;
    }

    h1 {
      text-align: center;
      color: #333;
    }

    .controls {
      margin-bottom: 20px;
      display: flex;
      justify-content: space-evenly;
      align-items: center;
      flex-wrap: wrap;
    }

    .subject-list {
      display: flex;
      flex-wrap: wrap;
      gap: 10px;
      margin-bottom: 20px;
      justify-content: center;
    }

    .subject-item {
      padding: 8px 15px;
      color: white;
      border-radius: 4px;
      cursor: move;
      user-select: none;
      position: relative;
    }

    .subject-item .edit-btn {
      position: absolute;
      top: -8px;
      right: -8px;
      background-color: #ff9800;
      color: white;
      border: none;
      border-radius: 50%;
      width: 16px;
      height: 16px;
      font-size: 10px;
      cursor: pointer;
      display: none;
    }

    .subject-item:hover .edit-btn {
      display: block;
    }

    .timetable {
      width: 100%;
      border-collapse: collapse;
      margin-top: 20px;
    }

    .timetable th,
    .timetable td {
      border: 1px solid #ddd;
      padding: 6px;
      text-align: center;
    }

    .timetable th {
      background-color: #f2f2f2;
      font-weight: bold;
    }

    .timetable td {
      min-height: 50px;
      height: 50px;
      vertical-align: middle;
    }

    .time-cell {
      font-size: 1.2rem;
      width: 180px;
      background-color: #f9f9f9;
      white-space: pre-wrap;
      word-wrap: break-word;
    }

    .section-time {
      font-size: 1.4rem;
      width: 60px;
      background-color: #f0f0f0;
      font-weight: bold;
      writing-mode: vertical-lr;
      text-orientation: upright;
    }

    .timetable-cell {
      background-color: #fff;
      position: relative;
    }

    .timetable-cell.dragover {
      background-color: #e6f7ff;
    }

    .subject-in-cell {
      font-size: 1.4rem;
      color: white;
      padding: 5px;
      border-radius: 3px;
      margin: 2px;
      cursor: pointer;
      position: relative;
    }

    .remove-btn {
      position: absolute;
      top: -8px;
      right: -8px;
      background-color: #ff5252;
      color: white;
      border: none;
      border-radius: 50%;
      width: 16px;
      height: 16px;
      font-size: 10px;
      cursor: pointer;
      display: none;
    }

    .subject-in-cell:hover .remove-btn {
      display: block;
    }

    .add-subject {
      display: flex;
      gap: 10px;
      align-items: center;
      margin-bottom: 10px;
      justify-content: center;
    }

    .add-subject input {
      padding: 8px;
      border: 1px solid #ddd;
      border-radius: 4px;
      width: 200px;
    }

    .add-subject button {
      padding: 8px 15px;
      background-color: #2196F3;
      color: white;
      border: none;
      border-radius: 4px;
      cursor: pointer;
    }

    .download-btns {
      display: flex;
      gap: 10px;
    }

    .download-btns button {
      padding: 8px 15px;
      background-color: #607d8b;
      color: white;
      border: none;
      border-radius: 4px;
      cursor: pointer;
    }

    .edit-subject-dialog {
      display: none;
      position: fixed;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
      background-color: white;
      padding: 20px;
      border-radius: 5px;
      box-shadow: 0 0 10px rgba(0, 0, 0, 0.3);
      z-index: 1000;
    }

    .edit-subject-dialog h3 {
      margin-top: 0;
    }

    .edit-subject-dialog input {
      padding: 8px;
      border: 1px solid #ddd;
      border-radius: 4px;
      width: 200px;
      margin-bottom: 10px;
    }

    .edit-subject-dialog button {
      padding: 8px 15px;
      margin-right: 10px;
      border: none;
      border-radius: 4px;
      cursor: pointer;
    }

    .edit-subject-dialog .save-btn {
      background-color: #4CAF50;
      color: white;
    }

    .edit-subject-dialog .cancel-btn {
      background-color: #f44336;
      color: white;
    }

    .edit-subject-dialog .delete-btn {
      background-color: #ff9800;
      color: white;
    }

    .time-controls {
      display: flex;
      gap: 10px;
      align-items: center;
    }

    .time-controls select {
      padding: 8px;
      border: 1px solid #ddd;
      border-radius: 4px;
    }

    .time-controls button {
      padding: 8px 15px;
      background-color: #2196F3;
      color: white;
      border: none;
      border-radius: 4px;
      cursor: pointer;
    }

    .edit-error {
      color: red;
      margin-bottom: 10px;
      display: none;
    }

    @media print {
      body * {
        visibility: hidden;
      }
      .timetable, .timetable th, .timetable td {
        visibility: visible;
      }
      .timetable {
        position: absolute;
        left: 0;
        top: 0;
        width: 100%;
      }
      .timetable th,
      .timetable td {
        border: 1px solid #000;
        background-color: transparent;
      }
      .subject-in-cell {
        background-color: transparent !important;
        border: none !important;
        color: #000 !important;
        font-weight: bold;
      }
      .remove-btn {
        display: none !important;
      }
    }

    .bw-version {
      filter: grayscale(100%) contrast(120%);
    }

    .bw-version .timetable th,
    .bw-version .timetable td {
      background-color: transparent;
      border-color: #000;
    }

    .bw-version .subject-in-cell {
      background-color: transparent !important;
      border: none !important;
      color: #000 !important;
      font-weight: bold;
    }
  </style>
</head>

<body>
  <h1>拖拽定制课程表</h1>

  <div class="add-subject">
    <input type="text" id="newSubject" placeholder="输入新科目">
    <button id="addSubjectBtn">添加科目</button>
  </div>

  <div class="subject-list" id="subjectList">
    <!-- 科目将通过JavaScript动态生成 -->
  </div>

  <div class="controls">
    <div class="time-controls">
      <select id="timeSectionSelect">
        <option value="morning">上午</option>
        <option value="afternoon">下午</option>
      </select>
      <button id="addTimeBtn">添加课时</button>
      <button id="removeTimeBtn">删除课时</button>
    </div>
    <div class="download-btns">
      <button id="resetBtn">重置课程表</button>
      <button id="downloadColorBtn">下载彩色课程表</button>
      <button id="downloadBWBtn">下载黑白课程表</button>
    </div>
  </div>

  <table class="timetable" id="timetable">
    <thead>
      <tr>
        <th colspan="9" contenteditable="true" style="font-size:1.6rem; text-align: center;">课程表</th>
      </tr>
      <tr>
        <th style="font-size:1.4rem; text-align: center;">时间</th>
        <th style="font-size:1.4rem; text-align: center;">课时</th>
        <th style="font-size:1.4rem; text-align: center;">星期一</th>
        <th style="font-size:1.4rem; text-align: center;">星期二</th>
        <th style="font-size:1.4rem; text-align: center;">星期三</th>
        <th style="font-size:1.4rem; text-align: center;">星期四</th>
        <th style="font-size:1.4rem; text-align: center;">星期五</th>
        <th style="font-size:1.4rem; text-align: center;">星期六</th>
        <th style="font-size:1.4rem; text-align: center;">星期日</th>
      </tr>
    </thead>
    <tbody id="timetableBody">
      <!-- 课时将通过JavaScript动态生成 -->
    </tbody>
  </table>

  <div class="edit-subject-dialog" id="editSubjectDialog">
    <h3>编辑科目</h3>
    <input type="text" id="editSubjectInput">
    <div class="edit-error" id="editError">科目已存在,请修改名称</div>
    <div>
      <button class="save-btn" id="saveSubjectBtn">保存</button>
      <button class="delete-btn" id="deleteSubjectBtn">删除</button>
      <button class="cancel-btn" id="cancelEditBtn">取消</button>
    </div>
  </div>
    <footer style="text-align: center;">
      <div>
        <p>&#169;Power by: ysjd22@52pojie | 99tonine@52pojie | black_hd@52pojie 修订优化</p>
      </div>
    </footer>
  <script>
  document.addEventListener('DOMContentLoaded', function () {
  const subjectList = document.getElementById('subjectList');
  const timetableBody = document.getElementById('timetableBody');
  const addSubjectBtn = document.getElementById('addSubjectBtn');
  const newSubjectInput = document.getElementById('newSubject');
  const resetBtn = document.getElementById('resetBtn');
  const downloadColorBtn = document.getElementById('downloadColorBtn');
  const downloadBWBtn = document.getElementById('downloadBWBtn');
  const editSubjectDialog = document.getElementById('editSubjectDialog');
  const editSubjectInput = document.getElementById('editSubjectInput');
  const editError = document.getElementById('editError');
  const saveSubjectBtn = document.getElementById('saveSubjectBtn');
  const deleteSubjectBtn = document.getElementById('deleteSubjectBtn');
  const cancelEditBtn = document.getElementById('cancelEditBtn');
  const timeSectionSelect = document.getElementById('timeSectionSelect');
  const addTimeBtn = document.getElementById('addTimeBtn');
  const removeTimeBtn = document.getElementById('removeTimeBtn');

  // 课时数据
  const timeData = {
    morning: [
      { name: "第一节", time: "7:40-8:20" },
      { name: "第二节", time: "8:30-9:10" },
      { name: "第三节", time: "9:20-10:00" },
      { name: "第四节", time: "10:10-10:50" }
    ],
    afternoon: [
      { name: "第五节", time: "14:00-14:40" },
      { name: "第六节", time: "14:50-15:30" },
      { name: "第七节", time: "15:40-16:20" },
      { name: "第八节", time: "16:30-17:10" }
    ]
  };

  // 科目颜色映射表
  let subjectColors = {};

  // 当前正在编辑的科目
  let currentEditingSubject = null;

  // 初始化应用
  function init() {
    // 从本地存储加载科目颜色
    const savedColors = localStorage.getItem('subjectColors');
    if (savedColors) {
      subjectColors = JSON.parse(savedColors);
    } else {
      // 默认科目颜色
      subjectColors = {
        '语文': '#4CAF50',
        '数学': '#2196F3',
        '英语': '#FF9800',
        '体育': '#E91E63',
        '音乐': '#00BCD4',
        '美术': '#8BC34A',
        '电脑': '#CDDC39'
      };
      // 保存默认科目
      localStorage.setItem('subjectColors', JSON.stringify(subjectColors));
    }

    // 初始化科目列表
    initSubjectList();
    
    // 加载其他数据
    loadTimetable();
  }

  // 初始化课程表
  function initTimetable() {
    timetableBody.innerHTML = '';
    
    // 添加上午课时
    addTimeSection('morning', '上午');
    
    // 添加下午课时
    addTimeSection('afternoon', '下午');
  }

  // 添加时间段
  function addTimeSection(section, sectionName) {
    const times = timeData[section];
    if (!times || times.length === 0) return;
    
    const firstRow = document.createElement('tr');
    firstRow.innerHTML = `
      <td class="section-time" rowspan="${times.length}">${sectionName}</td>
      <td class="time-cell" contenteditable="true">${times[0].name}<br>${times[0].time}</td>
      <td class="timetable-cell" data-time="${section}1" data-day="mon"></td>
      <td class="timetable-cell" data-time="${section}1" data-day="tue"></td>
      <td class="timetable-cell" data-time="${section}1" data-day="wed"></td>
      <td class="timetable-cell" data-time="${section}1" data-day="thu"></td>
      <td class="timetable-cell" data-time="${section}1" data-day="fri"></td>
            <td class="timetable-cell" data-time="${section}1" data-day="sat"></td>
      <td class="timetable-cell" data-time="${section}1" data-day="sun"></td>
    `;
    timetableBody.appendChild(firstRow);
    
    // 添加剩余课时
    for (let i = 1; i < times.length; i++) {
      const row = document.createElement('tr');
      row.innerHTML = `
        <td class="time-cell" contenteditable="true">${times[i].name}<br>${times[i].time}</td>
        <td class="timetable-cell" data-time="${section}${i+1}" data-day="mon"></td>
        <td class="timetable-cell" data-time="${section}${i+1}" data-day="tue"></td>
        <td class="timetable-cell" data-time="${section}${i+1}" data-day="wed"></td>
        <td class="timetable-cell" data-time="${section}${i+1}" data-day="thu"></td>
        <td class="timetable-cell" data-time="${section}${i+1}" data-day="fri"></td>
        <td class="timetable-cell" data-time="${section}${i+1}" data-day="sat"></td>
        <td class="timetable-cell" data-time="${section}${i+1}" data-day="sun"></td>
      `;
      timetableBody.appendChild(row);
    }
    
    // 设置单元格事件
    document.querySelectorAll('.timetable-cell').forEach(cell => {
      setupCellEvents(cell);
    });
    
    // 设置时间单元格事件
    document.querySelectorAll('.time-cell').forEach(cell => {
      cell.addEventListener('blur', saveTimeData);
    });
  }

  // 初始化科目列表
  function initSubjectList() {
    subjectList.innerHTML = '';
    for (const subject in subjectColors) {
      createSubjectItem(subject);
    }
  }

  // 创建科目项
  function createSubjectItem(subject) {
    const newSubject = document.createElement('div');
    newSubject.className = 'subject-item';
    newSubject.textContent = subject;
    newSubject.setAttribute('draggable', 'true');
    newSubject.style.backgroundColor = subjectColors[subject];
    
    // 添加编辑按钮
    const editBtn = document.createElement('button');
    editBtn.className = 'edit-btn';
    editBtn.textContent = '✎';
    editBtn.addEventListener('click', function(e) {
      e.stopPropagation();
      openEditDialog(subject);
    });
    newSubject.appendChild(editBtn);
    
    // 设置拖拽事件 - 只拖拽文本内容
    newSubject.addEventListener('dragstart', function (e) {
      e.dataTransfer.setData('text/plain', subject);
      e.dataTransfer.effectAllowed = 'copy';
      this.style.opacity = '0.5';
    });

    newSubject.addEventListener('dragend', function () {
      this.style.opacity = '1';
    });
    
    subjectList.appendChild(newSubject);
  }

  // 打开编辑对话框
  function openEditDialog(subject) {
    currentEditingSubject = subject;
    editSubjectInput.value = subject;
    editError.style.display = 'none';
    editSubjectDialog.style.display = 'block';
    editSubjectInput.focus();
  }

  // 关闭编辑对话框
  function closeEditDialog() {
    editSubjectDialog.style.display = 'none';
    currentEditingSubject = null;
    editError.style.display = 'none';
  }

  // 添加/更新科目
  addSubjectBtn.addEventListener('click', function () {
    const subjectName = newSubjectInput.value.trim();
    if (subjectName) {
      if (subjectColors[subjectName]) {
        alert('科目已存在');
        return;
      }
      
      // 为新科目分配颜色
      const colors = ['#4CAF50', '#2196F3', '#FF9800', '#9C27B0', 
              '#F44336', '#607D8B', '#795548', '#009688', 
              '#3F51B5', '#E91E63', '#00BCD4', '#8BC34A', '#CDDC39'];
      const usedColors = Object.values(subjectColors);
      const availableColors = colors.filter(c => !usedColors.includes(c));
      subjectColors[subjectName] = availableColors.length > 0 
        ? availableColors[0] 
        : `#${Math.floor(Math.random()*16777215).toString(16)}`;
      
      // 保存科目颜色
      localStorage.setItem('subjectColors', JSON.stringify(subjectColors));
      
      // 重新初始化科目列表
      initSubjectList();
      
      newSubjectInput.value = '';
    }
  });

  // 保存科目编辑
  saveSubjectBtn.addEventListener('click', function() {
    const newName = editSubjectInput.value.trim();
    if (!newName || !currentEditingSubject) return;
    
    // 检查科目是否已存在(除了当前编辑的科目)
    if (newName !== currentEditingSubject && subjectColors[newName]) {
      editError.style.display = 'block';
      return;
    }
    
    // 如果名称没变化,直接关闭对话框
    if (newName === currentEditingSubject) {
      closeEditDialog();
      return;
    }
    
    // 保存旧颜色
    const oldColor = subjectColors[currentEditingSubject];
    
    // 更新颜色映射
    subjectColors[newName] = oldColor;
    delete subjectColors[currentEditingSubject];
    
    // 保存科目颜色
    localStorage.setItem('subjectColors', JSON.stringify(subjectColors));
    
    // 更新科目列表中的科目
    initSubjectList();
    
    // 更新课程表中的科目
    document.querySelectorAll('.subject-in-cell').forEach(cell => {
      if (cell.textContent.replace('×', '').trim() === currentEditingSubject) {
        cell.textContent = newName;
        cell.style.backgroundColor = oldColor;
        
        // 更新删除按钮
        const removeBtn = cell.querySelector('.remove-btn');
        if (removeBtn) {
          const newRemoveBtn = removeBtn.cloneNode(true);
          cell.removeChild(removeBtn);
          newRemoveBtn.addEventListener('click', function(e) {
            e.stopPropagation();
            cell.parentNode.removeChild(cell);
            saveTimetable();
          });
          cell.appendChild(newRemoveBtn);
        }
      }
    });
    
    closeEditDialog();
    saveTimetable();
  });

  // 删除科目
  deleteSubjectBtn.addEventListener('click', function() {
    if (!currentEditingSubject) return;
    
    if (!confirm(`确定要删除科目"${currentEditingSubject}"吗?`)) {
      return;
    }
    
    // 从颜色映射中删除
    delete subjectColors[currentEditingSubject];
    
    // 保存科目颜色
    localStorage.setItem('subjectColors', JSON.stringify(subjectColors));
    
    // 从课程表中删除所有该科目
    document.querySelectorAll('.subject-in-cell').forEach(cell => {
      if (cell.textContent.replace('×', '').trim() === currentEditingSubject) {
        cell.parentNode.removeChild(cell);
      }
    });
    
    // 重新初始化科目列表
    initSubjectList();
    closeEditDialog();
    saveTimetable();
  });

  // 取消编辑
  cancelEditBtn.addEventListener('click', closeEditDialog);

  // 回车键添加科目
  newSubjectInput.addEventListener('keypress', function (e) {
    if (e.key === 'Enter') {
      addSubjectBtn.click();
    }
  });

  // 重置课程表
  resetBtn.addEventListener('click', function () {
    if (confirm('确定要重置整个课程表吗?所有课程安排将被清除。')) {
      document.querySelectorAll('.timetable-cell').forEach(cell => {
        cell.innerHTML = '';
      });
      localStorage.removeItem('timetableData');
      localStorage.removeItem('timeData');
    }
  });

  // 保存时间修改
  function saveTimeData() {
    const timeCells = document.querySelectorAll('.time-cell');
    const timeTextData = Array.from(timeCells).map(cell => cell.innerHTML);
    localStorage.setItem('timeData', JSON.stringify(timeTextData));
  }
// 实现下载课程表函数
      function downloadTimetable(isBW) {
        const timetable = document.getElementById('timetable');
        if (isBW) {
          timetable.classList.add('bw-version');
          const subjectInCells = timetable.querySelectorAll('.subject-in-cell');
          subjectInCells.forEach(cell => {
            cell.style.backgroundColor = 'transparent';
            cell.style.border = 'none';
          });
          const tableCells = timetable.querySelectorAll('th, td');
          tableCells.forEach(cell => {
            cell.style.backgroundColor = 'transparent';
          });
        }

        // 使用 html2canvas 库将表格转换为图片
        html2canvas(timetable, { useCORS: true }).then(canvas => {
          if (isBW) {
            timetable.classList.remove('bw-version');
            const subjectInCells = timetable.querySelectorAll('.subject-in-cell');
            subjectInCells.forEach(cell => {
              cell.style.backgroundColor = '';
              cell.style.border = '';
            });
            const tableCells = timetable.querySelectorAll('th, td');
            tableCells.forEach(cell => {
              cell.style.backgroundColor = '';
            });
          }

          // 创建下载链接
          const link = document.createElement('a');
          link.download = isBW ? '黑白课程表.png' : '彩色课程表.png';
          link.href = canvas.toDataURL();
          link.click();
        });
      }
  // 彩色版本下载
  downloadColorBtn.addEventListener('click', function () {
    downloadTimetable(false);
  });

  // 黑白版本下载 - 修改为不改变原课程表样式
  downloadBWBtn.addEventListener('click', function () {
    // 创建一个临时副本用于下载
    const timetable = document.getElementById('timetable');
    const clone = timetable.cloneNode(true);
    clone.classList.add('bw-version');
    
    // 隐藏原始表格
    timetable.style.visibility = 'hidden';
    
    // 将副本添加到body中
    clone.style.position = 'absolute';
    clone.style.left = '-9999px';
    document.body.appendChild(clone);
    
    // 使用html2canvas转换副本
    html2canvas(clone, { useCORS: true }).then(canvas => {
      // 创建下载链接
      const link = document.createElement('a');
      link.download = '黑白课程表.png';
      link.href = canvas.toDataURL();
      link.click();
      
      // 移除副本并恢复原始表格
      document.body.removeChild(clone);
      timetable.style.visibility = 'visible';
    });
  });

  // 设置单元格事件
  function setupCellEvents(cell) {
    cell.addEventListener('dragover', function (e) {
      e.preventDefault();
      e.dataTransfer.dropEffect = 'copy';
      this.classList.add('dragover');
    });

    cell.addEventListener('dragleave', function () {
      this.classList.remove('dragover');
    });

    cell.addEventListener('drop', function (e) {
      e.preventDefault();
      this.classList.remove('dragover');

      const subjectName = e.dataTransfer.getData('text/plain');
      if (subjectName) {
        addSubjectToCell(this, subjectName);
        saveTimetable();
      }
    });
  }

  // 添加科目到单元格
  function addSubjectToCell(cell, subjectName) {
    // 检查是否已存在相同科目
    const existingSubjects = cell.querySelectorAll('.subject-in-cell');
    for (let i = 0; i < existingSubjects.length; i++) {
      if (existingSubjects[i].textContent.replace('×', '').trim() === subjectName) {
        return; // 如果已存在相同科目,则不添加
      }
    }

    const subjectDiv = document.createElement('div');
    subjectDiv.className = 'subject-in-cell';
    subjectDiv.textContent = subjectName;
    subjectDiv.style.backgroundColor = subjectColors[subjectName] || '#4CAF50';

    const removeBtn = document.createElement('button');
    removeBtn.className = 'remove-btn';
    removeBtn.textContent = '×';
    removeBtn.addEventListener('click', function (e) {
      e.stopPropagation();
      cell.removeChild(subjectDiv);
      saveTimetable();
    });

    subjectDiv.appendChild(removeBtn);
    cell.appendChild(subjectDiv);
  }

  // 保存课程表数据到本地存储
  function saveTimetable() {
    const timetableData = {};

    document.querySelectorAll('.timetable-cell').forEach(cell => {
      const time = cell.getAttribute('data-time');
      const day = cell.getAttribute('data-day');
      const subjects = [];

      cell.querySelectorAll('.subject-in-cell').forEach(subjectDiv => {
        subjects.push(subjectDiv.textContent.replace('×', '').trim());
      });

      if (!timetableData[day]) {
        timetableData[day] = {};
      }

      timetableData[day][time] = subjects;
    });

    localStorage.setItem('timetableData', JSON.stringify(timetableData));
    localStorage.setItem('timeConfig', JSON.stringify(timeData));
  }

  // 从本地存储加载课程表数据
  function loadTimetable() {
    // 加载课时配置
    const savedTimeConfig = localStorage.getItem('timeConfig');
    if (savedTimeConfig) {
      const config = JSON.parse(savedTimeConfig);
      if (config.morning) timeData.morning = config.morning;
      if (config.afternoon) timeData.afternoon = config.afternoon;
    }

    const savedData = localStorage.getItem('timetableData');
    const savedTimeData = localStorage.getItem('timeData');

    // 初始化课程表
    initTimetable();

    if (savedData) {
      const timetableData = JSON.parse(savedData);

      for (const day in timetableData) {
        for (const time in timetableData[day]) {
          const cell = document.querySelector(`.timetable-cell[data-day="${day}"][data-time="${time}"]`);
          if (cell) {
            timetableData[day][time].forEach(subject => {
              addSubjectToCell(cell, subject);
            });
          }
        }
      }
    }

    if (savedTimeData) {
      const timeTextData = JSON.parse(savedTimeData);
      const timeCells = document.querySelectorAll('.time-cell');

      timeTextData.forEach((timeText, index) => {
        if (timeCells[index]) {
          timeCells[index].innerHTML = timeText;
        }
      });
    }
  }

  // 添加课时
  addTimeBtn.addEventListener('click', function() {
    const section = timeSectionSelect.value;
    const times = timeData[section];
    const newIndex = times.length + 1;
    
    // 添加新的课时数据
    times.push({
      name: `第${numberToChinese(newIndex)}节`,
      time: "点击编辑时间"
    });
    
    // 重新初始化课程表
    initTimetable();
    saveTimetable();
  });

  // 删除课时
  removeTimeBtn.addEventListener('click', function() {
    const section = timeSectionSelect.value;
    const times = timeData[section];
    
    if (times.length <= 1) {
      alert('至少保留一个课时');
      return;
    }
    
    if (!confirm(`确定要删除${section === 'morning' ? '上午' : '下午'}的最后一个课时吗?`)) {
      return;
    }
    
    // 删除最后一个课时
    times.pop();
    
    // 重新初始化课程表
    initTimetable();
    saveTimetable();
  });

  // 数字转中文
  function numberToChinese(num) {
    const chineseNums = ['零', '一', '二', '三', '四', '五', '六', '七', '八', '九', '十'];
    if (num <= 10) return chineseNums[num];
    if (num < 20) return '十' + (num % 10 === 0 ? '' : chineseNums[num % 10]);
    return chineseNums[Math.floor(num / 10)] + '十' + (num % 10 === 0 ? '' : chineseNums[num % 10]);
  }

  // 点击单元格时显示删除按钮
  document.addEventListener('click', function (e) {
    if (e.target.classList.contains('timetable-cell')) {
      e.target.querySelectorAll('.remove-btn').forEach(btn => {
        btn.style.display = 'block';
        setTimeout(() => {
          btn.style.display = 'none';
        }, 2000);
      });
    }
  });

  // 初始化应用
  init();
});
</script>

  <script src="https://www.codeae.com/data/attachment/forum/202507/20/ke.js"></script>
</body>

</html>