ARTICLE · 1111786
作业检查统计小工具——让AI写代码
作业检查统计小工具——让AI写代码
今天给大家分享一个作业检查统计的小程序,界面如上,能导出指定日期单科或所以科的检查统计情况。使用方法如下: 1、新建一个txt记事本,命名为:作业检查。 2、复制下面的代码,并粘贴在记事本中。 3、把记事本后缀名txt,修改为:html。 然后双击打开就是上述界面的了,有问题可留言哈,也可直接下载附件后修改后缀名直接用。 作业检查统计.txt 代码:

<!DOCTYPE html><htmllang="zh-CN"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>每日作业检查记录</title><style> * {margin: 0;padding: 0;box-sizing: border-box;font-family: 'Segoe UI', Roboto, system-ui, sans-serif; }body {background: #f1f5f9;padding: 20px16px;min-height: 100vh; }.container {max-width: 1300px;margin: 0 auto;background: white;border-radius: 24px;box-shadow: 08px24pxrgba(0,0,0,0.04);padding: 24px22px32px; }.app-title {font-size: 1.8rem;font-weight: 700;color: #1e40af;text-align: center;margin-bottom: 24px;padding-bottom: 16px;border-bottom: 3px solid #e2e8f0;letter-spacing: 2px; }.row-import-subject {display: flex;flex-wrap: wrap;align-items: center;gap: 12px24px;background: #f8fafc;padding: 10px18px;border-radius: 60px;border: 1px solid #e2e8f0;margin-bottom: 20px; }.import-group {display: flex;align-items: center;gap: 6px12px;flex-wrap: wrap; }.import-label {display: flex;align-items: center;gap: 6px;font-weight: 500;color: #1e293b; }.file-inline {position: relative;display: inline-block; }.file-inlineinput[type="file"] {position: absolute;left: 0; top: 0;opacity: 0;width: 100%; height: 100%;cursor: pointer; }.file-btn {background: white;border: 1px solid #cbd5e1;border-radius: 40px;padding: 4px16px;font-size: 0.9rem;color: #1e293b;display: inline-flex;align-items: center;gap: 4px;cursor: pointer;transition: background 0.1s; }.file-btn:hover { background: #eef2f6; }.file-name { font-size: 0.85rem; color: #475569; max-width: 140px; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }.subject-group {display: flex;align-items: center;gap: 6px12px;flex-wrap: wrap;margin-left: auto; }.subject-group-label { font-weight: 500; color: #1e293b; margin-right: 2px; }.subject-tag {padding: 4px14px;border-radius: 40px;font-size: 0.9rem;font-weight: 500;border: 1px solid #cbd5e1;background: white;color: #1e293b;cursor: pointer;transition: all 0.1s; user-select: none; }.subject-tag.active { background: #1e40af; border-color: #1e40af; color: white; }.subject-tag:hover { background: #e9edf2; }.student-section { margin: 8px014px; }.student-header {display: flex;justify-content: space-between;align-items: center;margin-bottom: 6px; }.student-header-title {font-weight: 600;font-size: 1rem;color: #0f172a;display: flex;align-items: center;gap: 8px; }.student-header-titlespan { background: #eef2f6; padding: 010px; border-radius: 40px; font-size: 0.8rem; color: #1e293b; }.legend { display: flex; gap: 14px; font-size: 0.85rem; color: #334155; }.legend-item { display: flex; align-items: center; gap: 4px; }.student-grid {background: #f8fafc;border-radius: 20px;padding: 12px14px;min-height: 260px;max-height: 380px;overflow-y: auto;display: flex;flex-wrap: wrap;align-content: flex-start;gap: 8px8px;border: 1px solid #e2e8f0;scrollbar-width: thin; }.student-item {display: flex;align-items: center;gap: 06px;background: white;border: 1px solid #d1d9e6;border-radius: 40px;padding: 6px10px6px14px;font-size: 1.1rem;font-weight: 500;box-shadow: 01px2pxrgba(0,0,0,0.02);transition: all 0.1s;cursor: pointer; }.student-item.selected { background: #dbeafe; border-color: #2563eb; box-shadow: 0001px#2563eb; }.student-name { margin-right: 4px; max-width: 110px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }.check-icon {display: inline-flex;align-items: center;justify-content: center;width: 24px;height: 24px;border-radius: 6px;font-size: 16px;font-weight: 600;background: #f1f5f9;border: 1px solid #cbd5e1;transition: 0.08s; user-select: none;line-height: 1;cursor: pointer; }.check-icon.done { background: #e0f2fe; border-color: #7dd3fc; color: #0369a1; }.check-icon.done::after { content: "✓"; }.check-icon.undone { background: #fee2e2; border-color: #fca5a5; color: #b91c1c; }.check-icon.undone::after { content: "✕"; }.excellent-icon {cursor: pointer;font-size: 1.1rem;opacity: 0.3;transition: opacity 0.2s; user-select: none;padding: 04px; }.excellent-icon.excellent-active { opacity: 1; }.row-action {display: flex;flex-wrap: wrap;align-items: center;gap: 10px18px;background: #f8fafc;padding: 10px16px;border-radius: 60px;border: 1px solid #e2e8f0;margin: 10px018px; }.add-student-group { display: flex; align-items: center; gap: 6px; }.add-student-groupinput { padding: 6px12px; border: 1px solid #cbd5e1; border-radius: 40px; font-size: 0.95rem; width: 130px; }.btn {background: white;border: 1px solid #cbd5e1;border-radius: 40px;padding: 6px16px;font-size: 0.9rem;font-weight: 500;cursor: pointer;transition: 0.1s;display: inline-flex;align-items: center;gap: 4px; }.btn-primary { background: #1e40af; border-color: #1e40af; color: white; }.btn-primary:hover { background: #1e3a8a; }.btn-danger { border-color: #f87171; color: #b91c1c; }.btn-danger:hover { background: #fee2e2; }.btn-success { background: #0b6e4f; border-color: #0b6e4f; color: white; }.btn-success:hover { background: #09593f; }.date-group { display: flex; align-items: center; gap: 6px; }.date-grouplabel { font-weight: 500; color: #1e293b; font-size: 0.9rem; }.date-groupinput[type="date"] { padding: 4px8px; border: 1px solid #cbd5e1; border-radius: 30px; font-size: 0.9rem; background: white; }.action-hint { font-size: 0.8rem; color: #475569; margin-left: auto; }.export-section { margin-top: 16px; padding-top: 16px; border-top: 1px solid #e2e8f0; }.export-top { display: flex; flex-wrap: wrap; align-items: center; gap: 12px24px; }.export-date-range { display: flex; align-items: center; gap: 10px18px; flex-wrap: wrap; }.export-date-rangelabel { font-weight: 500; font-size: 0.9rem; }.export-buttons { display: flex; flex-wrap: wrap; gap: 10px; }.btn-export { background: linear-gradient(135deg, #1e40af, #3b82f6); color: white; border: none; border-radius: 40px; padding: 6px16px; font-weight: 500; cursor: pointer; transition: all 0.2s; }.btn-export:hover { transform: translateY(-2px); box-shadow: 04px8pxrgba(30, 64, 175, 0.4); }.export-note { font-size: 0.8rem; color: #64748b; margin-top: 6px; padding: 8px; background: #f1f5f9; border-radius: 6px; }.footer-note { margin-top: 16px; font-size: 0.85rem; color: #4b5563; text-align: center; }</style></head><body><divclass="container"><h1class="app-title">📋 每日作业检查记录</h1><divclass="row-import-subject"><divclass="import-group"><spanclass="import-label">📂 导入名单</span><spanclass="file-inline"><inputtype="file"id="importFileInput"accept=".txt,.csv"><buttonclass="file-btn"id="importFileBtn">选择文件</button></span><spanclass="file-name"id="fileDisplayName">未选择</span></div><divclass="subject-group"><spanclass="subject-group-label">📚</span><spanclass="subject-tag active"data-subject="语文">语文</span><spanclass="subject-tag"data-subject="数学">数学</span><spanclass="subject-tag"data-subject="英语">英语</span><spanclass="subject-tag"data-subject="物理">物理</span><spanclass="subject-tag"data-subject="化学">化学</span><spanclass="subject-tag"data-subject="生物">生物</span></div></div><divclass="student-section"><divclass="student-header"><divclass="student-header-title">👥 学生列表 <spanid="studentCount">0</span></div><divclass="legend"><spanclass="legend-item">✅ 完成</span><spanclass="legend-item">✕ 未完成</span><spanclass="legend-item">⭐ 优秀</span></div></div><divclass="student-grid"id="studentGrid"></div></div><divclass="row-action"><divclass="add-student-group"><inputtype="text"id="newNameInput"placeholder="输入姓名"><buttonclass="btn btn-primary"id="addStudentBtn">➕ 加入</button></div><buttonclass="btn btn-danger"id="deleteSelectedBtn">🗑️ 删除选中</button><divclass="date-group"><label>📅 日期</label><inputtype="date"id="recordDateInput"value="2026-09-21"></div><buttonclass="btn btn-success"id="submitRecordBtn">✅ 确定录入</button><spanclass="action-hint">点击姓名选中,点击 ⭐ 标记优秀</span></div><divclass="export-section"><divclass="export-top"><spanstyle="font-weight:500;">📤 导出统计</span><divclass="export-date-range"><label>起始</label><inputtype="date"id="startDateExport"value="2026-09-15"><label>结束</label><inputtype="date"id="endDateExport"value="2026-09-21"></div><divclass="export-buttons"><buttonclass="btn-export"id="exportSingleBtn">📄 单科 (当前)</button><buttonclass="btn-export"id="exportAllBtn">📊 总表 (六科)</button></div></div><divclass="export-note">* 单科导出:☑ 完成,☒ 未完成,⭐ 优秀;总表导出:☑N次 ☒N次 ⭐N次</div></div><divclass="footer-note">点击姓名选中学生,点击 ⭐ 标记作业优秀</div></div><script>(function() {// ---------- 核心数据 ----------let students = [];let records = {};let excellentRecords = {};let currentSubject = '语文';let selectedStudentId = null;// DOMconst grid = document.getElementById('studentGrid');const countSpan = document.getElementById('studentCount');const newNameInput = document.getElementById('newNameInput');const addBtn = document.getElementById('addStudentBtn');const deleteBtn = document.getElementById('deleteSelectedBtn');const recordDateInput = document.getElementById('recordDateInput');const submitBtn = document.getElementById('submitRecordBtn');const fileInput = document.getElementById('importFileInput');const fileDisplay = document.getElementById('fileDisplayName');const subjectTags = document.querySelectorAll('.subject-tag');const startExp = document.getElementById('startDateExport');const endExp = document.getElementById('endDateExport');const exportSingle = document.getElementById('exportSingleBtn');const exportAll = document.getElementById('exportAllBtn');// ========== localStorage 持久化 ==========constSTORAGE_KEY = 'homework_records_final_v4';functionsaveAllData() {const dataToSave = { students, records, excellentRecords, currentSubject };try {localStorage.setItem(STORAGE_KEY, JSON.stringify(dataToSave)); } catch (e) {console.error('保存失败:', e); } }functionloadAllData() {try {const savedData = localStorage.getItem(STORAGE_KEY);if (savedData) {const parsed = JSON.parse(savedData);if (parsed.students) students = parsed.students;if (parsed.records) records = parsed.records;if (parsed.excellentRecords) excellentRecords = parsed.excellentRecords;if (parsed.currentSubject) currentSubject = parsed.currentSubject;returntrue; } } catch (e) {console.error('读取失败:', e); }returnfalse; }// ========== 渲染学生列表 ==========functionrenderStudents() { grid.innerHTML = '';if (students.length === 0) { grid.innerHTML = '<span style="padding:12px;color:#94a3b8;">暂无学生,请导入或添加</span>'; countSpan.textContent = '0';return; }const key = currentKey();const undoneMap = (key && records[key]) ? records[key] : {};const excellentMap = (key && excellentRecords[key]) ? excellentRecords[key] : {};const sorted = chineseSort(students.map(s => s.name));const idMap = {}; students.forEach(s => idMap[s.name] = s.id); sorted.forEach(name => {const id = idMap[name];const isUndone = undoneMap[name] === true;const isExcellent = excellentMap[name] === true;const div = document.createElement('div'); div.className = 'student-item';if (selectedStudentId === id) div.classList.add('selected'); div.dataset.id = id;const iconClass = isUndone ? 'undone' : 'done';const excellentClass = isExcellent ? 'excellent-active' : ''; div.innerHTML = ` <span class="student-name">${name}</span> <span class="check-icon ${iconClass}" data-id="${id}"></span> <span class="excellent-icon ${excellentClass}" data-id="${id}">⭐</span> `; grid.appendChild(div); }); countSpan.textContent = students.length;attachStudentEvents(); }functioncurrentKey() {const date = recordDateInput.value;return date ? `${date}_${currentSubject}` : null; }functionchineseSort(arr) {return arr.sort((a, b) => a.localeCompare(b, 'zh-CN')); }functionattachStudentEvents() {document.querySelectorAll('.student-item').forEach(item => { item.addEventListener('click', function(e) {if (e.target.classList.contains('check-icon') || e.target.classList.contains('excellent-icon')) return;document.querySelectorAll('.student-item').forEach(el => el.classList.remove('selected'));this.classList.add('selected'); selectedStudentId = this.dataset.id; }); });document.querySelectorAll('.check-icon').forEach(icon => { icon.addEventListener('click', function(e) { e.stopPropagation();if (this.classList.contains('done')) {this.classList.remove('done');this.classList.add('undone'); } else {this.classList.remove('undone');this.classList.add('done'); }saveAllData(); }); });document.querySelectorAll('.excellent-icon').forEach(icon => { icon.addEventListener('click', function(e) { e.stopPropagation();const id = this.dataset.id;const student = students.find(s => s.id === id);if (!student) return;this.classList.toggle('excellent-active');const key = currentKey();if (!excellentRecords[key]) excellentRecords[key] = {};if (this.classList.contains('excellent-active')) { excellentRecords[key][student.name] = true; } else {delete excellentRecords[key][student.name]; }saveAllData(); }); }); }// ========== 导出功能 ==========functionbuildExportData(singleSubject = true) {const start = startExp.value;const end = endExp.value;if (!start || !end) { alert('请选择起止日期'); returnnull; }if (start > end) { alert('起始日期不能晚于结束日期'); returnnull; }if (students.length === 0) { alert('学生列表为空'); returnnull; }const sortedStudents = chineseSort(students.map(s => s.name));const dateSet = newSet();for (let key ofObject.keys(records)) {const parts = key.split('_');if (parts.length !== 2) continue;const [d, sub] = parts;if (d >= start && d <= end) {if (!singleSubject || sub === currentSubject) { dateSet.add(d); } } }for (let key ofObject.keys(excellentRecords)) {const parts = key.split('_');if (parts.length !== 2) continue;const [d, sub] = parts;if (d >= start && d <= end) {if (!singleSubject || sub === currentSubject) { dateSet.add(d); } } }if (dateSet.size === 0) {alert('所选时间段无任何记录');returnnull; }const sortedDates = Array.from(dateSet).sort();const info = { start, end, isSingle: singleSubject, subject: currentSubject };if (singleSubject) {const sub = currentSubject;const rows = []; sortedStudents.forEach(name => {const row = { '姓名': name }; sortedDates.forEach(date => {const key = `${date}_${sub}`;const val = records[key]?.[name];const isExcellent = excellentRecords[key]?.[name];if (val === undefined && !isExcellent) { row[date] = ''; } else {let cellText = '';if (val !== undefined) {// 使用更通用的字符:☑ 完成,☒ 未完成 cellText += val ? '☒' : '☑'; }if (isExcellent) { cellText += ' ⭐'; } row[date] = cellText.trim(); } }); rows.push(row); });return { rows, columns: ['姓名', ...sortedDates], info }; } else {const allSubjects = ['语文','数学','英语','物理','化学','生物'];const rows = []; sortedStudents.forEach(name => {const row = { '姓名': name }; allSubjects.forEach(sub => {let doneCount = 0, undoneCount = 0, excellentCount = 0; sortedDates.forEach(date => {const key = `${date}_${sub}`;const val = records[key]?.[name];const isExcellent = excellentRecords[key]?.[name];if (val === true) undoneCount++;elseif (val === false) doneCount++;if (isExcellent) excellentCount++; });// 使用更通用的字符:☑ 完成,☒ 未完成 row[sub] = `☑${doneCount}次 ☒${undoneCount}次 ⭐${excellentCount}次`; }); rows.push(row); });return { rows, columns: ['姓名', ...allSubjects], info }; } }// 导出为Excel(含UTF-8 BOM确保符号正确显示)functiondownloadExcel(data, filename) {if (!data || !data.rows || data.rows.length === 0) {alert('没有数据可以导出');return; }try {const { rows, columns, info } = data;const subjectText = info.isSingle ? info.subject : '全部学科';const dateRangeText = `${info.start} 至 ${info.end}`;// 构建美观的HTML表格let html = '<html><head><meta charset="UTF-8"><title>每日作业检查记录</title></head><body>'; html += '<table border="1" cellpadding="8" cellspacing="0" style="border-collapse:collapse;font-family:Arial, sans-serif;font-size:13px;">';// 1. 大标题(合并所有列) html += `<tr><td colspan="${columns.length}" style="text-align:center;font-size:18px;font-weight:bold;background-color:#4472C4;color:white;padding:12px;border:2px solid #999;">`; html += '每日作业检查记录</td></tr>';// 2. 学科与日期范围信息 html += `<tr><td colspan="${columns.length}" style="text-align:center;font-size:14px;background-color:#D9E1F2;padding:8px;border:2px solid #999;">`; html += `学科:${subjectText} | 日期范围:${dateRangeText}</td></tr>`;// 3. 空行(视觉分隔) html += `<tr><td colspan="${columns.length}" style="padding:4px;"></td></tr>`;// 4. 表头行(蓝色背景) html += '<tr style="background-color:#4472C4;color:white;font-weight:bold;text-align:center;">'; columns.forEach(col => { html += `<th style="padding:8px;border:1px solid #999;">${col}</th>`; }); html += '</tr>';// 5. 数据行(斑马纹样式) rows.forEach((row, index) => {const bgColor = index % 2 === 0 ? '#F2F2F2' : '#FFFFFF'; html += `<tr style="background-color:${bgColor};">`; columns.forEach(col => {const cellValue = row[col] ?? '';const align = (col === '姓名') ? 'left;font-weight:bold;' : 'center;'; html += `<td style="padding:6px;border:1px solid #999;${align}">${cellValue}</td>`; }); html += '</tr>'; }); html += '</table></body></html>';// 添加UTF-8 BOM头,确保特殊符号在Excel中正确显示const blob = newBlob([`\uFEFF${html}`], { type: 'application/vnd.ms-excel;charset=utf-8' });const link = document.createElement('a'); link.href = URL.createObjectURL(blob); link.download = filename.endsWith('.xls') ? filename : filename + '.xls';document.body.appendChild(link); link.click();setTimeout(() => {document.body.removeChild(link);URL.revokeObjectURL(link.href); }, 100); } catch (error) {console.error('导出失败:', error);alert('导出失败: ' + error.message); } }// ========== 事件绑定 ========== subjectTags.forEach(tag => { tag.addEventListener('click', function() { subjectTags.forEach(t => t.classList.remove('active'));this.classList.add('active'); currentSubject = this.dataset.subject;renderStudents();saveAllData(); }); }); addBtn.addEventListener('click', function() {const name = newNameInput.value.trim();if (!name) return;if (students.some(s => s.name === name)) { alert('学生已存在'); return; } students.push({ id: 's_' + Date.now() + '_' + Math.random(), name }); newNameInput.value = '';renderStudents();saveAllData(); }); deleteBtn.addEventListener('click', function() {if (!selectedStudentId) {alert('请先点击姓名选中一个学生');return; }const idx = students.findIndex(s => s.id === selectedStudentId);if (idx === -1) return;const name = students[idx].name; students.splice(idx, 1);for (let key ofObject.keys(records)) {delete records[key][name]; }for (let key ofObject.keys(excellentRecords)) {delete excellentRecords[key][name]; } selectedStudentId = null;renderStudents();saveAllData(); }); submitBtn.addEventListener('click', function() {const date = recordDateInput.value;if (!date) { alert('请选择日期'); return; }if (students.length === 0) { alert('学生列表为空'); return; }const key = `${date}_${currentSubject}`;if (!records[key]) records[key] = {};document.querySelectorAll('.student-item').forEach(item => {const name = item.querySelector('.student-name').textContent;const icon = item.querySelector('.check-icon');const isUndone = icon.classList.contains('undone');if (isUndone) { records[key][name] = true; } else {delete records[key][name]; } });if (!excellentRecords[key]) excellentRecords[key] = {};document.querySelectorAll('.excellent-icon.excellent-active').forEach(icon => {const student = students.find(s => s.id === icon.dataset.id);if (student && student.name) { excellentRecords[key][student.name] = true; } });alert(`✅ 已保存 ${date} · ${currentSubject}`);saveAllData(); }); fileInput.addEventListener('change', function(e) {const file = e.target.files[0];if (!file) return; fileDisplay.textContent = file.name;const reader = newFileReader(); reader.onload = function(ev) {const lines = ev.target.result.split(/\r?\n/).map(s => s.trim()).filter(s => s);if (lines.length === 0) return; students = []; selectedStudentId = null; excellentRecords = {}; lines.forEach(n => {if (!students.some(s => s.name === n)) { students.push({ id: 's_' + Date.now() + '_' + Math.random(), name: n }); } });renderStudents();saveAllData(); }; reader.readAsText(file, 'UTF-8'); });document.getElementById('importFileBtn').addEventListener('click', function() { fileInput.click(); }); recordDateInput.addEventListener('change', renderStudents); exportSingle.addEventListener('click', function() {const data = buildExportData(true);if (data) {const filename = `单科_${currentSubject}_${startExp.value}_${endExp.value}.xls`;downloadExcel(data, filename); } }); exportAll.addEventListener('click', function() {const data = buildExportData(false);if (data) {const filename = `六科总表_${startExp.value}_${endExp.value}.xls`;downloadExcel(data, filename); } });// ========== 初始化 ==========functioninitialize() {const hasSavedData = loadAllData();if (!hasSavedData) {const initNames = ['张明', '李华', '王芳', '刘洋', '赵磊', '陈静', '周涛', '吴迪', '郑凯', '林曦']; initNames.forEach(n => {if (!students.some(s => s.name === n)) { students.push({ id: 's_init_' + n, name: n }); } });const today = '2026-09-21';const yesterday = '2026-09-20'; records[`${today}_语文`] = { '张明': false, '李华': false, '王芳': true, '刘洋': true }; excellentRecords[`${today}_语文`] = { '张明': true, '李华': true }; records[`${yesterday}_数学`] = { '赵磊': false, '陈静': true }; excellentRecords[`${yesterday}_数学`] = { '陈静': true };saveAllData(); } subjectTags.forEach(tag => { tag.classList.remove('active');if (tag.dataset.subject === currentSubject) { tag.classList.add('active'); } });renderStudents();const today = '2026-09-21'; recordDateInput.value = today; startExp.value = '2026-09-15'; endExp.value = today; }window.addEventListener('beforeunload', saveAllData);initialize();})();</script></body></html>