CodeAE 发表于 6 天前

html+JS写的一个可拖拽课程表

来自吾爱论坛大神的杰作


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>©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;
      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.name}<br>${times.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.name}<br>${times.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;
      
      // 添加编辑按钮
      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) {
                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 = availableColors.length > 0
                ? availableColors
                : `#${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) {
            editError.style.display = 'block';
            return;
      }
      
      // 如果名称没变化,直接关闭对话框
      if (newName === currentEditingSubject) {
            closeEditDialog();
            return;
      }
      
      // 保存旧颜色
      const oldColor = subjectColors;
      
      // 更新颜色映射
      subjectColors = oldColor;
      delete subjectColors;
      
      // 保存科目颜色
      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;
      
      // 保存科目颜色
      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.textContent.replace('×', '').trim() === subjectName) {
                return; // 如果已存在相同科目,则不添加
            }
      }

      const subjectDiv = document.createElement('div');
      subjectDiv.className = 'subject-in-cell';
      subjectDiv.textContent = subjectName;
      subjectDiv.style.backgroundColor = subjectColors || '#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) {
                timetableData = {};
            }

            timetableData = 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) {
                  const cell = document.querySelector(`.timetable-cell`);
                  if (cell) {
                        timetableData.forEach(subject => {
                            addSubjectToCell(cell, subject);
                        });
                  }
                }
            }
      }

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

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

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

    // 删除课时
    removeTimeBtn.addEventListener('click', function() {
      const section = timeSectionSelect.value;
      const times = timeData;
      
      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;
      if (num < 20) return '十' + (num % 10 === 0 ? '' : chineseNums);
      return chineseNums + '十' + (num % 10 === 0 ? '' : chineseNums);
    }

    // 点击单元格时显示删除按钮
    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>
测试代码
https://www.52pojie.cn/thread-2044570-1-1.html
页: [1]
查看完整版本: html+JS写的一个可拖拽课程表