你正在 萌芽版 · ⚡ 代码俱乐部 · ← 回到学院 · 萌芽版主页 · 总入口

← 代码俱乐部 · 创作者层 04 / 8

★ 代码俱乐部 · 压轴 ★

第 08 节 · 给一个你认识的人做工具

整个学院的压轴。不是练习项目 —— 是给爷爷/奶奶/弟弟用的真工具。功能完整、有测试、放在网上、那个人真的会用第二次。

清单

这是毕业证书

把这一项做完,你已经做了 一件真东西。不是练习。不是模拟。一个具体的人,因为你写的代码,今天比昨天好一点点。

这就是工程师的真本事。

← 上一节下一所:智能体实验室 →

动手练习 1:一个真实的待办事项应用

动手 一个完整的 Todo App
任务:下面是一个完整的待办事项应用。可以添加任务、标记完成、删除任务。试试使用它,或者改改样式和功能。这是一个真正能用的工具。
参考答案 / 更多功能

升级版,加了本地存储(刷新页面后数据不丢失):

<!DOCTYPE html>
<html>
<head>
  <style>
    /* 完整的样式代码 */
    * { margin: 0; padding: 0; box-sizing: border-box; }
    body { font-family: sans-serif; background: linear-gradient(135deg, #667eea, #764ba2); min-height: 100vh; padding: 20px; }
    .container { max-width: 700px; margin: 0 auto; }
    .card { background: white; border-radius: 12px; padding: 25px; box-shadow: 0 10px 30px rgba(0,0,0,0.2); }
    h1 { color: #667eea; margin-bottom: 10px; }
    .stats { color: #999; font-size: 14px; margin-bottom: 20px; }
    .input-area { display: flex; gap: 10px; margin-bottom: 20px; }
    input { flex: 1; padding: 12px; border: 2px solid #eee; border-radius: 5px; font-size: 14px; }
    input:focus { outline: none; border-color: #667eea; }
    button { padding: 12px 24px; background: #667eea; color: white; border: none; border-radius: 5px; cursor: pointer; font-weight: bold; }
    button:hover { background: #764ba2; }
    .todo-list { list-style: none; }
    .todo-item { padding: 15px; border-bottom: 1px solid #f0f0f0; display: flex; align-items: center; gap: 12px; transition: background 0.2s; }
    .todo-item:hover { background: #f9f9f9; }
    .todo-item input[type="checkbox"] { width: 20px; height: 20px; cursor: pointer; }
    .todo-item.done span { text-decoration: line-through; color: #ccc; }
    .delete-btn { margin-left: auto; background: #f44336; padding: 6px 12px; font-size: 12px; border-radius: 3px; }
    .empty { text-align: center; color: #ccc; padding: 40px; font-size: 16px; }
  </style>
</head>
<body>
  <div class="container">
    <div class="card">
      <h1>📝 我的待办清单</h1>
      <div class="stats">完成: <span id="stats">0/0</span></div>
      <div class="input-area">
        <input type="text" id="newTodo" placeholder="输入一个新任务..." onkeypress="if(event.key==='Enter') addTodo()" />
        <button onclick="addTodo()">添加</button>
      </div>
      <ul class="todo-list" id="todoList"></ul>
      <div class="empty" id="emptyMsg">还没有任务。来添加一个吧!</div>
    </div>
  </div>

  <script>
    let todos = JSON.parse(localStorage.getItem('todos')) || [];
    
    function addTodo() {
      let input = document.getElementById('newTodo');
      let text = input.value.trim();
      if (!text) return;
      todos.push({ id: Date.now(), text, done: false });
      input.value = '';
      save();
      render();
    }
    
    function toggleTodo(id) {
      let todo = todos.find(t => t.id === id);
      if (todo) todo.done = !todo.done;
      save();
      render();
    }
    
    function deleteTodo(id) {
      todos = todos.filter(t => t.id !== id);
      save();
      render();
    }
    
    function save() {
      localStorage.setItem('todos', JSON.stringify(todos));
    }
    
    function render() {
      if (todos.length === 0) {
        document.getElementById('emptyMsg').style.display = 'block';
        document.getElementById('todoList').innerHTML = '';
        document.getElementById('stats').innerText = '0/0';
        return;
      }
      
      document.getElementById('emptyMsg').style.display = 'none';
      let html = '';
      let done = todos.filter(t => t.done).length;
      
      for (let todo of todos) {
        let cls = todo.done ? 'done' : '';
        html += '<li class="todo-item ' + cls + '">' +
                '<input type="checkbox" ' + (todo.done ? 'checked' : '') + ' onchange="toggleTodo(' + todo.id + ')" />' +
                '<span>' + todo.text + '</span>' +
                '<button class="delete-btn" onclick="deleteTodo(' + todo.id + ')">删除</button>' +
                '</li>';
      }
      
      document.getElementById('todoList').innerHTML = html;
      document.getElementById('stats').innerText = done + '/' + todos.length;
    }
    
    render();
  </script>
</body>
</html>

关键进阶功能:localStorage 让任务在刷新页面后保留。这样用户关掉浏览器再打开,他的清单还在。

动手练习 2:给你身边的人设计一个真工具

这个练习没有代码框。你需要自己决定:

思考 设计你自己的工具
任务:想想你身边有没有人(爷爷、奶奶、弟弟、同学)在做一件"重复的、烦人的、但你能帮他们自动化"的事。比如:记录家务清单、追踪零花钱、计划游戏时间、整理购物清单。选一个,写一个网页工具帮他们。

在下面写你的计划:

看参考

一个真实的例子:

"我要给奶奶做一个'用药提醒'的网页。

功能:
1. 奶奶每天需要吃三种药,分别在早中晚。
2. 网页上显示大大的'今天早上该吃药了'。
3. 奶奶点'我吃过了',就记录下来。
4. 晚上还没吃,网页就变红色,提醒她别忘了。

为什么是她最需要的:她现在用纸条记,经常丢。这个网页用大字体,永远不会丢。"

关键:这不是"我想做什么",而是"我身边的人真正需要什么"。前者通常没人用,后者会被用很多次。

小测验:什么是真正的"产品"

小测 你理解"给真人做工具"的本质了吗?
下面哪个最能说明"什么是真正有用的工具"?
解释:这就是整个课程的核心 —— 从第 1 节的"把代码打出来",到最后一节的"做一个真人真的会用的工具"。功能多不是好,有用才是好。有人回来用第二次,才是你成功的证明。