从能跑到好维护 | 课型:理实一体课 | 建议课时:2节
模拟终端:输入Git命令,可视化看到仓库状态变化。
新窗口运行 下载源码<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>Git演练场</title>
<style>
body { font-family: Consolas, "Microsoft YaHei", monospace; background: #1e1e2e; color: #cdd6f4; margin: 0; padding: 24px; }
#term { background: #11111b; border-radius: 10px; padding: 18px; min-height: 300px; }
#input { display: flex; margin-top: 12px; }
#cmd { flex: 1; background: #313244; border: none; color: #cdd6f4; padding: 12px;
border-radius: 8px; font-size: 15px; font-family: inherit; }
.out { color: #a6e3a1; } .err { color: #f38ba8; } .hint { color: #6c7086; font-size: 14px; }
#viz { margin-top: 16px; display: flex; gap: 20px; }
.zone { background: #313244; border-radius: 10px; padding: 14px; flex: 1; min-height: 90px; }
.zone h3 { margin: 0 0 8px; font-size: 14px; color: #89b4fa; }
.file { background: #45475a; border-radius: 6px; padding: 4px 10px; margin: 4px 0; display: inline-block; margin-right: 6px; }
</style>
</head>
<body>
<h2>Git 命令演练场</h2>
<p class="hint">试试:git init → git add index.html → git commit -m "first" → git log</p>
<div id="viz">
<div class="zone"><h3>工作区</h3><div id="work"></div></div>
<div class="zone"><h3>暂存区</h3><div id="stage"></div></div>
<div class="zone"><h3>仓库(提交历史)</h3><div id="repo"></div></div>
</div>
<div id="term"><div class="hint">$ 等待输入……</div></div>
<div id="input"><input id="cmd" placeholder="输入git命令后回车" autofocus></div>
<script>
const state = { init: false, work: ['index.html', 'style.css', 'app.js'], stage: [], repo: [] };
const term = document.getElementById('term');
function render() {
document.getElementById('work').innerHTML = state.work.map(f => '<span class="file">' + f + '</span>').join('') || '<span class="hint">空</span>';
document.getElementById('stage').innerHTML = state.stage.map(f => '<span class="file">' + f + '</span>').join('') || '<span class="hint">空</span>';
document.getElementById('repo').innerHTML = state.repo.map(c => '<div class="file">📦 ' + c + '</div>').join('') || '<span class="hint">空</span>';
}
function print(text, cls) {
const d = document.createElement('div'); d.textContent = text; d.className = cls || 'out';
term.appendChild(d); term.scrollTop = term.scrollHeight;
}
function run(line) {
print('$ ' + line, 'hint');
const parts = line.trim().split(/\s+/);
if (parts[0] !== 'git') { print('暂只支持git命令', 'err'); return; }
const sub = parts[1];
if (sub === 'init') { state.init = true; print('初始化空仓库成功'); }
else if (!state.init) { print('请先 git init', 'err'); }
else if (sub === 'add') {
const f = parts[2];
if (f === '.') { state.stage.push(...state.work); state.work = []; print('已暂存全部文件'); }
else if (state.work.includes(f)) { state.work.splice(state.work.indexOf(f), 1); state.stage.push(f); print('已暂存 ' + f); }
else print('文件不存在:' + (f || ''), 'err');
}
else if (sub === 'commit') {
if (!state.stage.length) { print('暂存区为空', 'err'); return; }
const msg = parts.slice(3).join(' ').replace(/"/g, '') || 'commit';
state.repo.push(msg + '(含' + state.stage.length + '个文件)');
state.stage = [];
print('[main] ' + msg);
}
else if (sub === 'log') { state.repo.slice().reverse().forEach(c => print('commit: ' + c)); if (!state.repo.length) print('暂无提交', 'hint'); }
else if (sub === 'status') { print('工作区:' + state.work.length + ' 暂存区:' + state.stage.length + ' 已提交:' + state.repo.length); }
else print('未知子命令:' + sub, 'err');
render();
}
document.getElementById('cmd').addEventListener('keydown', e => {
if (e.key === 'Enter' && e.target.value.trim()) { run(e.target.value); e.target.value = ''; }
});
render();
</script>
</body>
</html>任务目标:完成计时器模块化重构并用Git管理
| 任务内容与评分 |
|---|
| 任务1:为计时器代码补充规范注释(15分) |
| 任务2:拆分render.js/timer.js/main.js三模块(30分) |
| 任务3:git init并完成三次有意义提交(25分) |
| 任务4:故意改坏代码后回滚到上一版本(15分) |
| 任务5:编写项目README.md(15分) |