这是为您生成的“记事本”交互式HTML案例,一个可直接运行的待办事项管理工具。

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">记事本 · 简洁待办</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: system-ui, -apple-system, 'Segoe UI', Roboto, 'Helvetica Neue', sans-serif;
}
body {
background: linear-gradient(145deg, #f6f8fc 0%, #eef2f7 100%);
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
padding: 16px;
margin: 0;
}
.notebook {
max-width: 560px;
width: 100%;
background: #ffffff;
border-radius: 32px;
box-shadow: 0 20px 40px -12px rgba(0, 20, 40, 0.25), 0 8px 16px -8px rgba(0, 20, 40, 0.1);
padding: 28px 24px 32px;
transition: all 0.2s ease;
border: 1px solid rgba(255, 255, 255, 0.5);
backdrop-filter: blur(2px);
}
.header {
display: flex;
align-items: center;
gap: 10px;
margin-bottom: 22px;
padding-bottom: 16px;
border-bottom: 2px solid #f0f3f8;
}
.header h1 {
font-size: 1.8rem;
font-weight: 650;
color: #1e293b;
letter-spacing: -0.02em;
display: flex;
align-items: center;
gap: 10px;
}
.header h1 span {
background: #e9eef7;
border-radius: 40px;
padding: 4px 12px;
font-size: 0.9rem;
font-weight: 500;
color: #3b4a5f;
}
.header i {
color: #4070b0;
font-size: 28px;
}
/* 输入区域 */
.editor {
display: flex;
flex-direction: column;
gap: 14px;
margin-bottom: 28px;
}
.input-group {
display: flex;
align-items: center;
background: #f9fbfd;
border-radius: 50px;
border: 1.5px solid #e1e8f0;
transition: all 0.2s;
padding: 4px;
box-shadow: inset 0 2px 4px rgba(0,0,0,0.02);
}
.input-group:focus-within {
border-color: #3f7ac6;
background: white;
box-shadow: 0 0 0 3px rgba(63, 122, 198, 0.15);
}
.input-group input {
flex: 1;
border: none;
background: transparent;
padding: 12px 20px;
font-size: 1rem;
outline: none;
color: #1e293b;
font-weight: 450;
}
.input-group input::placeholder {
color: #8896ab;
font-weight: 350;
}
.btn-add {
background: #3f7ac6;
border: none;
color: white;
width: 48px;
height: 48px;
border-radius: 50%;
font-size: 28px;
font-weight: 300;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
transition: 0.15s;
box-shadow: 0 4px 10px rgba(63, 122, 198, 0.35);
margin: 4px;
line-height: 1;
}
.btn-add:hover {
background: #2f62a8;
transform: scale(0.96);
}
.btn-add:active {
transform: scale(0.92);
}
/* 分类标签 */
.category-tabs {
display: flex;
gap: 8px;
margin-bottom: 22px;
flex-wrap: wrap;
}
.cat-btn {
background: transparent;
border: 1.5px solid #d7e0ea;
padding: 8px 16px;
border-radius: 40px;
font-size: 0.9rem;
font-weight: 500;
color: #41546e;
cursor: pointer;
transition: all 0.15s;
flex: 1 0 auto;
display: flex;
align-items: center;
justify-content: center;
gap: 6px;
background: #f5f8fc;
}
.cat-btn i {
font-size: 16px;
}
.cat-btn.active {
background: #1e293b;
border-color: #1e293b;
color: white;
box-shadow: 0 6px 12px rgba(0, 0, 0, 0.08);
}
.cat-btn .count {
background: rgba(0,0,0,0.08);
padding: 2px 8px;
border-radius: 30px;
font-size: 0.8rem;
font-weight: 600;
}
.cat-btn.active .count {
background: rgba(255,255,255,0.25);
}
/* 列表区域 */
.task-container {
background: #ffffff;
border-radius: 24px;
padding: 6px 4px;
max-height: 380px;
overflow-y: auto;
margin-bottom: 6px;
scrollbar-width: thin;
scrollbar-color: #bdc8d8 #f0f4fa;
}
.task-container::-webkit-scrollbar {
width: 6px;
}
.task-container::-webkit-scrollbar-track {
background: #f0f4fa;
border-radius: 20px;
}
.task-container::-webkit-scrollbar-thumb {
background: #bdc8d8;
border-radius: 20px;
}
.task-item {
display: flex;
align-items: center;
padding: 14px 16px;
background: #ffffff;
border-radius: 18px;
margin-bottom: 8px;
transition: all 0.15s;
border: 1px solid transparent;
box-shadow: 0 1px 4px rgba(0,0,0,0.02);
}
.task-item:hover {
background: #f7faff;
border-color: #dfe7f2;
}
.task-item.completed .task-text {
text-decoration: line-through;
color: #a0aebe;
}
.task-item.completed {
opacity: 0.75;
}
.task-check {
margin-right: 12px;
flex-shrink: 0;
}
.task-check input {
width: 22px;
height: 22px;
cursor: pointer;
accent-color: #3f7ac6;
border-radius: 6px;
}
.task-content {
flex: 1;
min-width: 0;
}
.task-text {
font-size: 1.05rem;
font-weight: 500;
color: #1e293b;
overflow-wrap: break-word;
word-break: break-word;
line-height: 1.4;
}
.task-meta {
display: flex;
align-items: center;
gap: 8px;
margin-top: 4px;
flex-wrap: wrap;
}
.task-category {
font-size: 0.75rem;
background: #eef3fa;
padding: 3px 10px;
border-radius: 40px;
color: #304a6e;
font-weight: 500;
}
.task-date {
font-size: 0.75rem;
color: #7d8da4;
display: flex;
align-items: center;
gap: 4px;
}
.task-delete {
background: transparent;
border: none;
color: #b9c6d6;
font-size: 20px;
cursor: pointer;
padding: 8px 8px;
border-radius: 30px;
transition: all 0.15s;
margin-left: 8px;
flex-shrink: 0;
line-height: 1;
}
.task-delete:hover {
color: #e5475c;
background: #fdecee;
}
.empty-state {
text-align: center;
padding: 36px 20px;
color: #9badc2;
font-size: 0.95rem;
}
.empty-state i {
font-size: 40px;
opacity: 0.5;
display: block;
margin-bottom: 10px;
}
/* 底部统计 */
.footer-actions {
display: flex;
justify-content: space-between;
align-items: center;
margin-top: 14px;
padding-top: 18px;
border-top: 2px solid #f0f3f8;
font-size: 0.9rem;
color: #526482;
flex-wrap: wrap;
gap: 10px;
}
.stats {
font-weight: 450;
}
.clear-btn {
background: transparent;
border: 1px solid #d9e1ec;
padding: 8px 14px;
border-radius: 40px;
cursor: pointer;
color: #526482;
font-size: 0.85rem;
transition: 0.15s;
display: flex;
align-items: center;
gap: 6px;
font-weight: 500;
}
.clear-btn:hover {
background: #f2f6fa;
border-color: #b9c5d8;
color: #1f2c3d;
}
.clear-btn:active {
background: #e7ecf3;
}
/* 模拟text icon 使用emoji或unicode */
.icon-note { font-size: 26px; }
/* 移动端适配 */
@media (max-width: 480px) {
.notebook { padding: 20px 16px; }
.header h1 { font-size: 1.5rem; }
.btn-add { width: 44px; height: 44px; }
.task-item { padding: 12px; }
}
</style>
</head>
<body>
<div class="notebook">
<!-- 头部 -->
<div class="header">
<h1>
<span class="icon-note">📓</span> 记事本
<span class="badge">待办</span>
</h1>
</div>
<!-- 新增待办 -->
<div class="editor">
<div class="input-group">
<input type="text" id="newTaskInput" placeholder="写点什么… 按回车即可" maxlength="120" autofocus>
<button class="btn-add" id="addTaskBtn" aria-label="添加">+</button>
</div>
<div class="category-tabs" id="categoryTabs">
<button class="cat-btn active" data-cat="all">📋 全部 <span class="count" id="countAll">0</span></button>
<button class="cat-btn" data-cat="工作">💼 工作 <span class="count" id="countWork">0</span></button>
<button class="cat-btn" data-cat="生活">🏖️ 生活 <span class="count" id="countLife">0</span></button>
<button class="cat-btn" data-cat="学习">📚 学习 <span class="count" id="countStudy">0</span></button>
</div>
</div>
<!-- 待办列表容器 -->
<div class="task-container" id="taskListContainer">
<!-- 动态插入 item -->
</div>
<!-- 底部 统计 清空完成 -->
<div class="footer-actions">
<div class="stats" id="statsText">共 0 项 · 已完成 0 项</div>
<button class="clear-btn" id="clearCompletedBtn">🧹 清理已完成</button>
</div>
</div>
<script>
(function(){
// ----- 数据模型 -----
let tasks = []; // { id, text, category, completed, date }
// 当前选中的分类筛选 (all / 工作 / 生活 / 学习)
let currentFilter = 'all';
// DOM 元素
const inputEl = document.getElementById('newTaskInput');
const addBtn = document.getElementById('addTaskBtn');
const listContainer = document.getElementById('taskListContainer');
const statsText = document.getElementById('statsText');
const clearCompletedBtn = document.getElementById('clearCompletedBtn');
// 分类标签 & 计数器
const catButtons = document.querySelectorAll('.cat-btn');
const countAllEl = document.getElementById('countAll');
const countWorkEl = document.getElementById('countWork');
const countLifeEl = document.getElementById('countLife');
const countStudyEl = document.getElementById('countStudy');
// ----- 辅助函数 -----
function formatDate(ts) {
const d = new Date(ts);
const y = d.getFullYear();
const m = String(d.getMonth() + 1).padStart(2,'0');
const day = String(d.getDate()).padStart(2,'0');
return `${y}.${m}.${day}`;
}
// 生成ID
function generateId() {
return Date.now() + Math.random().toString(36).substr(2, 8);
}
// 获取当前分类下所有任务 (筛选)
function getFilteredTasks() {
if (currentFilter === 'all') return tasks;
return tasks.filter(t => t.category === currentFilter);
}
// 计算分类计数
function updateCounts() {
const total = tasks.length;
const work = tasks.filter(t => t.category === '工作').length;
const life = tasks.filter(t => t.category === '生活').length;
const study = tasks.filter(t => t.category === '学习').length;
countAllEl.textContent = total;
countWorkEl.textContent = work;
countLifeEl.textContent = life;
countStudyEl.textContent = study;
// 更新底部统计
const completed = tasks.filter(t => t.completed).length;
statsText.textContent = `共 ${total} 项 · 已完成 ${completed} 项`;
}
// 渲染任务列表
function renderList() {
const filtered = getFilteredTasks();
if (filtered.length === 0) {
listContainer.innerHTML = `
<div class="empty-state">
<i>🗒️</i>
<span>${currentFilter === 'all' ? '暂无记录,添加一条吧' : '这个分类还没有任务'}</span>
</div>`;
return;
}
// 排序:未完成在前,完成在后,日期最新靠前(也可不加)
const sorted = [...filtered].sort((a,b) => {
if (a.completed !== b.completed) return a.completed ? 1 : -1;
return b.date - a.date;
});
let html = '';
for (const task of sorted) {
const isCompletedClass = task.completed ? 'completed' : '';
const categoryLabel = task.category;
const dateStr = formatDate(task.date);
html += `
<div class="task-item ${isCompletedClass}" data-id="${task.id}">
<div class="task-check">
<input type="checkbox" ${task.completed ? 'checked' : ''} data-id="${task.id}" class="toggle-check" aria-label="切换完成状态">
</div>
<div class="task-content">
<div class="task-text">${escapeHtml(task.text)}</div>
<div class="task-meta">
<span class="task-category">${categoryLabel}</span>
<span class="task-date">📅 ${dateStr}</span>
</div>
</div>
<button class="task-delete" data-id="${task.id}" aria-label="删除任务">🗑️</button>
</div>
`;
}
listContainer.innerHTML = html;
// 绑定动态事件 (checkbox change, 删除按钮)
listContainer.querySelectorAll('.toggle-check').forEach(checkbox => {
checkbox.addEventListener('change', function(e) {
const id = this.dataset.id;
toggleTaskCompletion(id);
});
});
listContainer.querySelectorAll('.task-delete').forEach(btn => {
btn.addEventListener('click', function(e) {
const id = this.dataset.id;
deleteTask(id);
});
});
}
// 简易转义函数(防止XSS)
function escapeHtml(text) {
const div = document.createElement('div');
div.textContent = text;
return div.innerHTML;
}
// ----- 核心操作 -----
// 添加任务
function addTask(text) {
const trimmed = text.trim();
if (!trimmed) {
alert('请输入内容');
return false;
}
// 自动选择分类(基于默认?这里简单使用默认“生活”,但更好是用户手动选择,但这里可根据tab?但更简单:选择一个分类 // 我们使用当前激活的tab来分配?但全部时默认'生活'多一些?但更合理保留为最后一个点击的tab? 我们默认选择"生活")
// 但为了更符合记事本直觉,默认分类 = 当前tab(如果当前是工作、生活或学习则使用;如果选择“全部”,则使用“生活”)
let defaultCategory = '生活';
if (currentFilter !== 'all') {
defaultCategory = currentFilter;
}
const newTask = {
id: generateId(),
text: trimmed,
category: defaultCategory,
completed: false,
date: Date.now()
};
tasks.unshift(newTask); // 新任务在前面
inputEl.value = '';
updateCounts();
renderList();
return true;
}
// 切换完成状态
function toggleTaskCompletion(id) {
const task = tasks.find(t => t.id === id);
if (task) {
task.completed = !task.completed;
updateCounts();
renderList();
}
}
// 删除任务
function deleteTask(id) {
tasks = tasks.filter(t => t.id !== id);
updateCounts();
renderList();
}
// 清空已完成
function clearCompleted() {
tasks = tasks.filter(t => !t.completed);
updateCounts();
renderList();
}
// 更新激活分类样式
function setActiveCategory(cat) {
catButtons.forEach(btn => {
const dataCat = btn.dataset.cat;
if (dataCat === cat) {
btn.classList.add('active');
} else {
btn.classList.remove('active');
}
});
}
// 切换筛选
function switchFilter(cat) {
currentFilter = cat;
setActiveCategory(cat);
renderList();
}
// ----- 初始化事件 -----
// 添加按钮
addBtn.addEventListener('click', () => {
addTask(inputEl.value);
});
// 回车添加
inputEl.addEventListener('keypress', (e) => {
if (e.key === 'Enter') {
e.preventDefault();
addTask(inputEl.value);
}
});
// 分类点击
catButtons.forEach(btn => {
btn.addEventListener('click', (e) => {
const cat = btn.dataset.cat;
switchFilter(cat);
});
});
// 清空已完成
clearCompletedBtn.addEventListener('click', clearCompleted);
// 预置一些示例数据(展示案例效果)
function loadExampleData() {
const now = Date.now();
tasks = [
{ id: 'ex1', text: '整理周报 & 提交', category: '工作', completed: false, date: now - 2 * 86400000 },
{ id: 'ex2', text: '买牛奶和全麦面包', category: '生活', completed: true, date: now - 86400000 },
{ id: 'ex3', text: '阅读《人类简史》30页', category: '学习', completed: false, date: now - 5 * 3600000 },
{ id: 'ex4', text: '预约牙医 (下周二)', category: '生活', completed: false, date: now - 3600000 },
{ id: 'ex5', text: '完成项目原型设计', category: '工作', completed: false, date: now - 30 * 60000 },
];
// 完成的示例放第二个
updateCounts();
renderList();
}
// 启动时加载示例数据
loadExampleData();
setActiveCategory('all'); // 默认全部
// 额外细节:点击分类后新增任务使用该分类
// 已经在addTask中使用currentFilter逻辑
})();
</script>
</body>
</html>
核心功能与操作指南
您可以通过以下几个模块,轻松管理您的待办事项。
- 任务添加:在顶部的输入框中输入内容,点击 “+”按钮 或按下 回车键 即可快速添加新任务,新任务会默认归类到您当前选中的分类标签下。
- 分类管理:通过 “全部”、“工作”、“生活”、“学习” 四个标签,您可以快速筛选查看不同类别的任务,每个标签旁的数字会实时显示该类别的任务数量。
- 任务操作:点击任务前的 复选框 可以标记任务为“已完成”,已完成的任务会显示删除线,点击任务右侧的 垃圾桶图标 可以删除该条记录。
- 数据统计与清理:底部区域会显示“总任务数”和“已完成数”,您可以随时点击 “清理已完成” 按钮,一键移除所有已完成的任务,保持列表整洁。
优化建议: 页面中的示例数据(如“整理周报”)是用于演示的,您可以在代码的 loadExampleData 函数中找到并修改或删除它们,以替换为您自己的初始任务。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播