戰(zhàn):從零構(gòu)建會(huì)斷電自救的賽博城市)
用 Claude 現(xiàn)場從零生成一個(gè)會(huì)斷電自救的賽博城市從提示詞到可運(yùn)行 HTML 的完整實(shí)踐最近很多開發(fā)者在討論用 Claude 生成網(wǎng)頁項(xiàng)目從商品落地頁、個(gè)人主頁到各種小游戲確實(shí)“能生成”和“生成得好”之間差別非常大。大部分演示視頻里AI 只是生成了一張靜態(tài)畫面節(jié)奏一到就停下來真正有價(jià)值的是讓 AI 生成一個(gè)“有系統(tǒng)行為”的頁面——不是畫一張賽博朋克風(fēng)格的圖而是一個(gè)會(huì)運(yùn)轉(zhuǎn)、會(huì)響應(yīng)事件、有內(nèi)部狀態(tài)的城市模擬器。這篇文章要分享的就是一條完整的實(shí)操路徑用 Claude 從零生成一個(gè)單文件 HTML 賽博城市并且這個(gè)城市具備“斷電自救”的能力。所謂斷電自救不是簡單地把燈熄滅再亮起來而是要讓城市內(nèi)部有一套電力管理系統(tǒng)檢測斷電事件、按優(yōu)先級調(diào)度備用電源、分批恢復(fù)關(guān)鍵設(shè)施供電。整座城市會(huì)“活著”——燈火會(huì)流動(dòng)、大樓會(huì)閃爍、斷電時(shí)會(huì)有自己的應(yīng)急反應(yīng)。這背后真正的技術(shù)變化是 Claude Code 這類終端 AI 編程工具把“想法到可運(yùn)行原型”的轉(zhuǎn)換成本壓到了很低的程度。過去手寫這樣一個(gè)項(xiàng)目至少需要半天到一天要處理 Canvas 繪制、動(dòng)畫循環(huán)、狀態(tài)管理等一堆細(xì)節(jié)現(xiàn)在用 Claude Code可以在命令行里通過對話逐步完成。但這條路線也有不少坑提示詞怎么寫、生成后怎么審閱、斷電邏輯怎么調(diào)、安裝過程會(huì)遇到什么報(bào)錯(cuò)很多新手都是卡在這些地方。讀完這篇文章你會(huì)得到三樣?xùn)|西第一一套完整的 Claude Code 環(huán)境搭建和配置方法包括常見的安裝問題排查。 第二一份可以直接復(fù)制的賽博城市提示詞模板以及 Claude 生成代碼后的審閱思路。 第三一個(gè)具備斷電自救機(jī)制的 HTML 單頁項(xiàng)目實(shí)現(xiàn)能直接運(yùn)行和擴(kuò)展。如果你正打算用 AI 生成復(fù)雜網(wǎng)頁項(xiàng)目或者已經(jīng)試過但效果不理想這篇文章應(yīng)該能幫你少走不少彎路。1. 為什么用 Claude 生成一個(gè)“會(huì)自救”的賽博城市先問一個(gè)更底層的問題網(wǎng)頁版的 Claude 和很多在線 AI 工具已經(jīng)能生成 HTML 頁面為什么還要專門用 Claude Code 在終端里做這件事原因在于項(xiàng)目復(fù)雜度。一個(gè)賽博城市長什么樣和它如何運(yùn)轉(zhuǎn)是兩個(gè)難度級別完全不同的事。如果只是讓 Claude 生成一個(gè)賽博城市頁面它很可能給你一個(gè)帶霓虹燈的靜態(tài)頁面背景是深紫色漸變中間是幾棟發(fā)光的建筑剪影燈是 CSS 動(dòng)畫在閃爍。視覺效果不錯(cuò)但沒有任何系統(tǒng)邏輯。頁面打開后是固定的用戶沒法干預(yù)城市也不會(huì)對任何事件做出反應(yīng)。但“斷電自救”這個(gè)需求直接把項(xiàng)目從“視覺實(shí)現(xiàn)”拉到了“系統(tǒng)模擬”的層級。它要求頁面具備幾個(gè)關(guān)鍵能力城市里有多個(gè)建筑每個(gè)建筑都有電力狀態(tài)、用電量、優(yōu)先級和備用電池容量。城市正常運(yùn)行時(shí)電網(wǎng)統(tǒng)一供電所有建筑正常發(fā)光。某個(gè)時(shí)刻觸發(fā)斷電事件電網(wǎng)停止供電建筑燈光開始變化。系統(tǒng)按優(yōu)先級啟動(dòng)備用電源關(guān)鍵設(shè)施優(yōu)先恢復(fù)非關(guān)鍵設(shè)施延遲恢復(fù)或降載運(yùn)行。整個(gè)過程中畫面要有持續(xù)的動(dòng)畫反饋?zhàn)層脩裟苤庇^看到電力調(diào)度過程。這些邏輯加起來意味著頁面里需要有一組數(shù)據(jù)結(jié)構(gòu)、一個(gè)狀態(tài)機(jī)、一個(gè)調(diào)度算法以及一個(gè)持續(xù)運(yùn)行的渲染循環(huán)。這不是一句提示詞能一次搞定的需要分步驟、分模塊地讓 AI 生成更需要你去理解、調(diào)整和驗(yàn)證。這正是 Claude Code 擅長的地方。與網(wǎng)頁版對話相比Claude Code 直接跑在你本地的工作目錄里能讀取和編輯真實(shí)文件能運(yùn)行命令查看結(jié)果能配合 Git 做版本管理。你可以在這個(gè)文件里不斷迭代每次只讓 AI 改一個(gè)模塊然后運(yùn)行驗(yàn)證再繼續(xù)下一步。這個(gè)工作流更加接近真實(shí)的開發(fā)過程而不僅僅是一次性的對話式問答。此外Claude Code 還支持 Skill 等擴(kuò)展機(jī)制。Skill 本質(zhì)上是一種預(yù)先定義好的工作流模板你可以把“生成賽博城市項(xiàng)目”寫成一份 Skill規(guī)定好目錄結(jié)構(gòu)、技術(shù)選型和代碼風(fēng)格之后每次生成都復(fù)用同一套標(biāo)準(zhǔn)。對于需要重復(fù)創(chuàng)建項(xiàng)目的團(tuán)隊(duì)來說這個(gè)機(jī)制很值得研究。關(guān)于 Claude 是不是“沒有靈感”我的判斷是對于這種小型創(chuàng)意項(xiàng)目它完全夠用。真正決定項(xiàng)目質(zhì)量的不是 AI 的能力上限而是你的提示詞質(zhì)量和工程素養(yǎng)。2. Claude Code 是什么以及它和網(wǎng)頁版 Claude 的區(qū)別很多朋友對 Claude 的認(rèn)知停留在網(wǎng)頁聊天窗口。實(shí)際上Claude 生態(tài)系統(tǒng)里有一整套開發(fā)工具其中和程序員關(guān)系最近的就是 Claude Code。Claude Code 是 Anthropic 推出的終端編程助手。它以命令行工具的形式運(yùn)行可以直接在項(xiàng)目目錄中工作。你可以讓它讀取文件、修改代碼、執(zhí)行命令、運(yùn)行測試甚至讓它自己提交 Git commit。它和網(wǎng)頁版的區(qū)別可以參考這個(gè)表格維度網(wǎng)頁版 ClaudeClaude Code使用場景問答、文檔總結(jié)、一次性代碼生成多文件項(xiàng)目迭代、終端工作流、本地代碼修改文件訪問需要手動(dòng)上傳可以直接讀取工作目錄中的文件命令執(zhí)行不支持支持執(zhí)行終端命令工作方式單輪或多輪對話可以持續(xù)迭代、增量修改適合項(xiàng)目小型腳本、單文件頁面中大型項(xiàng)目、需要反復(fù)調(diào)優(yōu)的開發(fā)任務(wù)對賽博城市這類項(xiàng)目來說網(wǎng)頁版 Claude 也能生成但迭代體驗(yàn)完全不同。你用網(wǎng)頁版生成一個(gè)單文件 HTML如果后續(xù)想調(diào)整斷電邏輯需要復(fù)制粘貼整段代碼重新提問非常痛苦。用 Claude Code直接說“把醫(yī)院建筑的備用電池容量提高一倍”它就會(huì)精準(zhǔn)地修改對應(yīng)代碼行改完你立刻運(yùn)行看效果。另一種常見使用方式是在 VSCode 中配置 Claude Code。在 VSCode 的終端里啟動(dòng) Claude Code左邊是編輯器右邊是 AI 對話窗口改代碼的同時(shí)可以直接觀察文件變化。對于 HTML 頁面這種需要頻繁預(yù)覽效果的項(xiàng)目這種配置體驗(yàn)很好。需要說明的是Claude Code 是一個(gè)相對新的工具它的安裝方式、配置項(xiàng)和可用模型會(huì)隨版本更新而變化。這篇文章重點(diǎn)演示通用思路具體版本號(hào)請以實(shí)際安裝時(shí)為準(zhǔn)。3. 環(huán)境準(zhǔn)備安裝與配置 Claude Code這一步我們解決一個(gè)核心問題把 Claude Code 裝好、跑起來、能訪問你的項(xiàng)目目錄。3.1 前置條件Claude Code 依賴 Node.js 運(yùn)行環(huán)境因此需要先確認(rèn)本機(jī)已經(jīng)安裝 Node.js 和 npm。在終端中執(zhí)行node --version npm --version如果提示找不到命令需要先安裝 Node.js。安裝完成后建議重新打開終端再執(zhí)行一次確保 PATH 已生效。另外需要確保本機(jī)網(wǎng)絡(luò)能夠正常訪問相關(guān)服務(wù)。這里不展開具體網(wǎng)絡(luò)細(xì)節(jié)但提醒一句使用 Claude 相關(guān)服務(wù)前請確認(rèn)你的網(wǎng)絡(luò)環(huán)境和賬號(hào)使用方式符合服務(wù)條款和當(dāng)?shù)胤梢蟆?.2 安裝 Claude CodeClaude Code 的安裝方式主要是通過 npm 全局安裝。在終端執(zhí)行npm install -g anthropic-ai/claude-code安裝完成后在任意目錄執(zhí)行claude首次運(yùn)行會(huì)進(jìn)入初始化流程。通常會(huì)要求你登錄 Claude 賬號(hào)并授權(quán)按照終端提示完成即可。這個(gè)授權(quán)是為了讓 Claude Code 能以你的身份調(diào)用模型服務(wù)。安裝過程中有幾個(gè)常見報(bào)錯(cuò)這里提前說明后面還會(huì)在常見問題章節(jié)詳細(xì)展開。第一個(gè)是error: claude native binary not installed. either postinstall did not run...。這個(gè)問題通常出現(xiàn)在 npm 包安裝不完整的時(shí)候可能原因包括網(wǎng)絡(luò)中斷、npm 緩存問題或安裝權(quán)限不足。常見的處理方法是刪除全局 node_modules 中的相關(guān)目錄后重新安裝npm uninstall -g anthropic-ai/claude-code npm cache clean --force npm install -g anthropic-ai/claude-code第二個(gè)是賬號(hào)或組織層面的限制。有些用戶會(huì)看到類似your organization has disabled claude subscription access for claude code的提示這說明當(dāng)前賬號(hào)所屬的組織在管理后臺(tái)關(guān)閉了 Claude Code 的訂閱訪問權(quán)限。這種情況需要聯(lián)系組織管理員開通或者使用個(gè)人賬號(hào)。第三個(gè)是模型版本不識(shí)別。Claude Code 對模型名稱有版本要求如果你在配置中填入了它不認(rèn)識(shí)的模型名會(huì)報(bào)錯(cuò)。解決方法是在配置中使用官方支持的模型標(biāo)識(shí)。3.3 在 VSCode 中使用 Claude Code如果你習(xí)慣在編輯器里工作可以在 VSCode 的終端中直接啟動(dòng) Claude Code。打開你的項(xiàng)目目錄在 VSCode 內(nèi)置終端里執(zhí)行claudeClaude Code 會(huì)自動(dòng)識(shí)別當(dāng)前工作目錄后續(xù)生成的文件都會(huì)放在這個(gè)目錄下。注意建議把 Claude Code 放在一個(gè)獨(dú)立的 Git 倉庫中方便追蹤每一步改動(dòng)。如果項(xiàng)目被 AI 改壞了隨時(shí)可以回滾。3.4 創(chuàng)建項(xiàng)目目錄在正式生成賽博城市之前先建一個(gè)干凈的項(xiàng)目目錄mkdir cyber-city cd cyber-city git init claude這樣做的原因是Claude Code 會(huì)在當(dāng)前目錄生成文件如果目錄里已有其他項(xiàng)目AI 可能會(huì)錯(cuò)誤地讀取和修改無關(guān)文件。獨(dú)立目錄能隔離風(fēng)險(xiǎn)也方便測試。4. 賽博城市架構(gòu)設(shè)計(jì)一開始就要想清楚系統(tǒng)這一步最容易被忽略。很多人一上來就讓 Claude “生成一個(gè)賽博城市”結(jié)果 AI 返回一個(gè)結(jié)構(gòu)混亂的頁面改起來很痛苦。正確做法是先想清楚這個(gè)城市的技術(shù)架構(gòu)再讓 AI 照著架構(gòu)實(shí)現(xiàn)。我們把賽博城市拆成四個(gè)模塊4.1 建筑實(shí)體層每個(gè)建筑都是一組數(shù)據(jù)對象包含以下屬性屬性含義示例值id建筑唯一標(biāo)識(shí)hospital-01name建筑名稱中央醫(yī)院type建筑類型hospital / residential / commercial />請用 HTML CSS JavaScript 在單個(gè) HTML 文件中實(shí)現(xiàn)一個(gè)賽博朋克風(fēng)格的動(dòng)態(tài)城市模擬器要求如下 1. 使用 Canvas 繪制整座城市城市中包含至少 12 棟建筑建筑類型包括醫(yī)院、數(shù)據(jù)中心、住宅樓、商業(yè)樓、警察局。 2. 每棟建筑都是一個(gè) JavaScript 對象包含以下屬性id、name、type、x、y、width、height、priority、powerUsage、batteryCapacity、batteryLevel、status。 3. 城市有一個(gè)電網(wǎng)系統(tǒng)正常運(yùn)行狀態(tài)下所有建筑由電網(wǎng)供電建筑燈光正常顯示。 4. 實(shí)現(xiàn)一個(gè)全局函數(shù) triggerBlackout()調(diào)用后電網(wǎng)停電建筑燈光按調(diào)度策略變化 - 優(yōu)先級為 1 的建筑如醫(yī)院優(yōu)先切換備用電池?zé)艄獗3置髁恋伾優(yōu)榫G色。 - 優(yōu)先級為 2 的建筑如數(shù)據(jù)中心切換備用電池?zé)艄獗3炙{(lán)色。 - 優(yōu)先級為 3 及以上的建筑如住宅、商業(yè)在電池電量耗盡后燈光熄滅。 5. 實(shí)現(xiàn)一個(gè)全局函數(shù) restorePower()調(diào)用后電網(wǎng)恢復(fù)供電所有建筑恢復(fù)正常燈光。 6. 頁面底部顯示一個(gè)控制面板包含兩個(gè)按鈕“觸發(fā)斷電” 和 “恢復(fù)供電”。 7. 使用 requestAnimationFrame 實(shí)現(xiàn)動(dòng)畫循環(huán)每幀更新電池電量并重繪畫面。 8. 視覺風(fēng)格深紫色夜空背景建筑使用霓虹燈配色夜空中添加星星和流動(dòng)的云層。 9. 在畫面左上角顯示當(dāng)前城市電力狀態(tài)包括電網(wǎng)狀態(tài)和總電池電量。 10. 代碼需要完整可運(yùn)行不要省略關(guān)鍵邏輯。這段提示詞看起來很長但每一項(xiàng)都是在約束 AI 的行為。特別是第 4 條它明確規(guī)定了斷電后的表現(xiàn)方式——不同優(yōu)先級建筑的燈光變化不同這是“自救”機(jī)制的核心。生成代碼后不要直接運(yùn)行就結(jié)束。先讓 Claude 解釋它的設(shè)計(jì)思路請解釋以下內(nèi)容 1. triggerBlackout() 函數(shù)內(nèi)部如何分配備用電源 2. 如果電池電量不足會(huì)發(fā)生什么 3. 動(dòng)畫循環(huán)每幀執(zhí)行了哪些計(jì)算這一步非常重要。AI 生成的代碼不一定符合你的預(yù)期讓它解釋邏輯能幫你快速發(fā)現(xiàn)理解偏差。如果發(fā)現(xiàn)調(diào)度邏輯不對直接讓它修改當(dāng)前調(diào)度邏輯是按順序分配電量我希望改成電池電量按優(yōu)先級動(dòng)態(tài)分配如果優(yōu)先級為 1 的建筑電量不足可以從優(yōu)先級為 2 的建筑借電。請修改 triggerBlackout() 函數(shù)。這種迭代式開發(fā)是 AI 編程工具相比傳統(tǒng)搜索引擎最大的優(yōu)勢。6. 核心代碼實(shí)現(xiàn)HTML、CSS 與 JavaScript這一節(jié)我們直接進(jìn)入代碼實(shí)現(xiàn)??紤]到可讀性我會(huì)把完整的賽博城市拆成三個(gè)部分來展示HTML 骨架、CSS 樣式、JavaScript 核心邏輯。最終你可以把它們合并成一個(gè)index.html文件運(yùn)行。6.1 HTML 骨架!DOCTYPE html html langzh-CN head meta charsetUTF-8 meta nameviewport contentwidthdevice-width, initial-scale1.0 title賽博城市 - 斷電自救模擬器/title style /* CSS 樣式見 6.2 */ /style /head body div idcity-container canvas idcityCanvas width900 height600/canvas div idstatus-panel div classstatus-item span classlabel電網(wǎng)狀態(tài)/span span idgridStatus classvalue正常/span /div div classstatus-item span classlabel總電池電量/span span idbatteryTotal classvalue100%/span /div /div div idcontrol-panel button idblackoutBtn onclicktriggerBlackout()觸發(fā)斷電/button button idrestoreBtn onclickrestorePower()恢復(fù)供電/button /div /div script // JavaScript 邏輯見 6.3 和 6.4 /script /body /html這段骨架定義了三塊區(qū)域#cityCanvasCanvas 畫布城市就在這塊畫布上繪制。#status-panel左上角的電力狀態(tài)面板展示電網(wǎng)狀態(tài)和總電池電量。#control-panel底部控制按鈕用來觸發(fā)斷電和恢復(fù)供電。6.2 CSS 樣式* { margin: 0; padding: 0; box-sizing: border-box; } body { background: #0a0015; font-family: Courier New, monospace; display: flex; justify-content: center; align-items: center; min-height: 100vh; } #city-container { position: relative; width: 900px; height: 600px; border: 2px solid #ff00ff; box-shadow: 0 0 20px #ff00ff66, 0 0 40px #00ffff44; border-radius: 8px; overflow: hidden; } #cityCanvas { display: block; background: linear-gradient(to bottom, #0a0015 0%, #1a0033 50%, #0d002b 100%); } #status-panel { position: absolute; top: 15px; left: 15px; background: rgba(10, 0, 20, 0.8); border: 1px solid #00ffff; border-radius: 6px; padding: 10px 16px; color: #00ffff; font-size: 14px; } .status-item { margin-bottom: 4px; } .value { font-weight: bold; } #control-panel { position: absolute; bottom: 15px; left: 50%; transform: translateX(-50%); display: flex; gap: 12px; } #control-panel button { padding: 8px 20px; background: transparent; border: 1px solid #ff00ff; border-radius: 4px; color: #ff00ff; font-family: Courier New, monospace; font-size: 14px; cursor: pointer; transition: all 0.3s; } #control-panel button:hover { background: #ff00ff22; box-shadow: 0 0 10px #ff00ff; }這套樣式做了幾件事讓頁面背景變深紫營造賽博朋克氛圍給 Canvas 容器加上霓虹邊框把狀態(tài)面板放在左上角把控制按鈕放在底部居中。按鈕的懸停效果讓它看起來更像一個(gè)可交互的模擬器。6.3 JavaScript城市數(shù)據(jù)與渲染循環(huán)接下來是核心邏輯。先定義建筑數(shù)據(jù)結(jié)構(gòu)和城市初始化邏輯。// 文件路徑index.html 內(nèi) script 標(biāo)簽 const canvas document.getElementById(cityCanvas); const ctx canvas.getContext(2d); const gridStatusEl document.getElementById(gridStatus); const batteryTotalEl document.getElementById(batteryTotal); // 城市狀態(tài) let isGridUp true; let blackoutTimer null; // 建筑構(gòu)造函數(shù) class Building { constructor(building) { this.id building.id; this.name building.name; this.type building.type; this.x building.x; this.y building.y; this.width building.width; this.height building.height; this.priority building.priority; this.powerUsage building.powerUsage; this.batteryCapacity building.batteryCapacity; this.batteryLevel building.batteryCapacity; this.status grid; // grid / battery / off // 顏色配置 this.colors building.colors || { grid: #ffdd00, battery: #00ff88, off: #1a1a2e }; } // 繪制建筑 draw() { let color; if (this.status grid) { color this.colors.grid; } else if (this.status battery) { color this.colors.battery; } else { color this.colors.off; } // 建筑主體 ctx.fillStyle #12122e; ctx.fillRect(this.x, this.y, this.width, this.height); // 建筑燈光 ctx.strokeStyle color; ctx.lineWidth 2; ctx.shadowBlur 15; ctx.shadowColor color; // 繪制窗口簡單的網(wǎng)格線表示窗戶燈光 const windowRows Math.floor(this.height / 12); const windowCols Math.floor(this.width / 10); for (let row 0; row windowRows; row) { for (let col 0; col windowCols; col) { ctx.fillStyle Math.random() 0.3 ? color : transparent; ctx.fillRect(this.x 4 col * 10, this.y 4 row * 12, 4, 5); } } ctx.shadowBlur 0; } } // 城市建筑列表 const buildings [ new Building({ id: hospital-01, name: 中央醫(yī)院, type: hospital, x: 100, y: 350, width: 90, height: 140, priority: 1, powerUsage: 120, batteryCapacity: 500, colors: { grid: #00ff88, battery: #00ff88, off: #1a1a2e } }), new Building({ id: data-center-01, name: 數(shù)據(jù)中心, type: data-center, x: 620, y: 300, width: 100, height: 120, priority: 2, powerUsage: 180, batteryCapacity: 350, colors: { grid: #00ccff, battery: #00ccff, off: #1a1a2e } }), new Building({ id: police-01, name: 警察局, type: police, x: 400, y: 380, width: 80, height: 100, priority: 2, powerUsage: 80, batteryCapacity: 250, colors: { grid: #ff5500, battery: #00ff88, off: #1a1a2e } }), // 住宅樓和商業(yè)樓可以按相同方式繼續(xù)添加 new Building({ id: residential-01, name: 住宅樓, type: residential, x: 220, y: 380, width: 70, height: 110, priority: 3, powerUsage: 60, batteryCapacity: 120, colors: { grid: #ffdd00, battery: #00ff88, off: #1a1a2e } }), new Building({ id: commercial-01, name: 商業(yè)大廈, type: commercial, x: 500, y: 320, width: 80, height: 160, priority: 4, powerUsage: 140, batteryCapacity: 150, colors: { grid: #ff00ff, battery: #00ff88, off: #1a1a2e } }) ]; // 繪制夜空背景 function drawSky() { const gradient ctx.createLinearGradient(0, 0, 0, canvas.height); gradient.addColorStop(0, #050010); gradient.addColorStop(0.5, #12002e); gradient.addColorStop(1, #0d002b); ctx.fillStyle gradient; ctx.fillRect(0, 0, canvas.width, canvas.height); // 星星 ctx.fillStyle #ffffff; for (let i 0; i 80; i) { const x Math.random() * canvas.width; const y Math.random() * canvas.height * 0.4; const size Math.random() * 1.5 0.5; ctx.globalAlpha Math.random() * 0.7 0.3; ctx.fillRect(x, y, size, size); } ctx.globalAlpha 1; } // 計(jì)算總電池電量 function getTotalBattery() { const total buildings.reduce((sum, b) sum b.batteryLevel, 0); const max buildings.reduce((sum, b) sum b.batteryCapacity, 0); return max 0 ? Math.round((total / max) * 100) : 0; } // 動(dòng)畫循環(huán) function animate() { drawSky(); // 如果電網(wǎng)斷電每幀減少電池電量 if (!isGridUp) { buildings.forEach(building { if (building.status battery) { building.batteryLevel Math.max(0, building.batteryLevel - 0.3); if (building.batteryLevel 0) { building.status off; } } }); } // 繪制所有建筑 buildings.forEach(building building.draw()); // 更新狀態(tài)面板 gridStatusEl.textContent isGridUp ? 正常 : 斷電; gridStatusEl.style.color isGridUp ? #00ff88 : #ff0044; batteryTotalEl.textContent getTotalBattery() %; requestAnimationFrame(animate); } // 啟動(dòng)動(dòng)畫 animate();這段代碼有四個(gè)關(guān)鍵點(diǎn)第一Building類封裝了建筑的所有屬性。每個(gè)建筑都有自己的電池容量和當(dāng)前電量狀態(tài)有三種grid電網(wǎng)供電、battery備用電池供電、off斷電。第二draw()方法根據(jù)狀態(tài)選擇不同顏色。電網(wǎng)正常時(shí)不同建筑有各自的霓虹色電池供電時(shí)統(tǒng)一變?yōu)榫G色表示應(yīng)急狀態(tài)斷電后變?yōu)樯钌?。第三animate()是動(dòng)畫主循環(huán)每幀調(diào)用一次requestAnimationFrame。電網(wǎng)斷電時(shí)電池電量逐幀減少當(dāng)某一棟建筑電量耗盡燈光熄滅。第四星星的背景用Math.random()生成每一幀都會(huì)變化讓夜空有一種動(dòng)態(tài)閃爍的感覺。6.4 JavaScript斷電自救調(diào)度邏輯接下來是最核心的部分——triggerBlackout()和restorePower()。// 觸發(fā)斷電 function triggerBlackout() { if (!isGridUp) return; isGridUp false; // 按優(yōu)先級排序priority 數(shù)字越小優(yōu)先級越高 const sortedBuildings [...buildings].sort((a, b) a.priority - b.priority); // 依次分配備用電源 sortedBuildings.forEach(building { if (building.priority 2) { // 高優(yōu)先級建筑切換到電池供電 building.status battery; } else { // 低優(yōu)先級建筑檢查電池剩余電量 if (building.batteryLevel 0) { building.status battery; } else { building.status off; } } }); console.log([電網(wǎng)] 斷電事件觸發(fā)啟動(dòng)應(yīng)急電源調(diào)度); } // 恢復(fù)供電 function restorePower() { if (isGridUp) return; isGridUp true; // 所有建筑恢復(fù)電網(wǎng)供電 buildings.forEach(building { building.status grid; building.batteryLevel building.batteryCapacity; }); console.log([電網(wǎng)] 電力恢復(fù)城市供電正常); } // 自動(dòng)斷電演示頁面加載 10 秒后觸發(fā)一次斷電 setTimeout(() { if (isGridUp) { triggerBlackout(); } }, 10000);這段邏輯的核心是“按優(yōu)先級調(diào)度”。觸發(fā)斷電時(shí)先把所有建筑按 priority 排序然后依次讓它們切換狀態(tài)。priority 為 1 和 2 的建筑無條件切換為電池供電priority 更高的建筑需要檢查自身電池是否還有余量有余量才能切換否則直接斷電。這個(gè)調(diào)度算法雖然簡單但已經(jīng)能模擬真實(shí)的災(zāi)備場景醫(yī)院和數(shù)據(jù)中心這些關(guān)鍵設(shè)施優(yōu)先保障供電普通住宅和商業(yè)樓只能靠自身電池硬撐電池耗盡后燈光熄滅。城市看起來就像真的在“自救”。restorePower()的邏輯很簡單電網(wǎng)恢復(fù)后所有建筑回到正常狀態(tài)同時(shí)把電池電量充滿為下一次斷電事件做準(zhǔn)備。代碼末尾加了一個(gè) 10 秒定時(shí)器頁面打開 10 秒后會(huì)自動(dòng)觸發(fā)一次斷電方便演示效果。如果你想手動(dòng)控制可以刪掉這個(gè)定時(shí)器只用按鈕觸發(fā)。7. 運(yùn)行與效果驗(yàn)證代碼寫好之后驗(yàn)證環(huán)節(jié)同樣重要。下面介紹如何運(yùn)行這個(gè)項(xiàng)目以及如何判斷斷電自救機(jī)制是否正常工作。7.1 運(yùn)行項(xiàng)目從 Claude Code 退出后在項(xiàng)目目錄中直接用瀏覽器打開index.html即可open index.html或者使用 VSCode 的 Live Server 插件啟動(dòng)本地服務(wù)這樣改代碼后瀏覽器會(huì)自動(dòng)刷新體驗(yàn)更好。如果不想安裝任何插件也可以在終端里啟動(dòng)一個(gè)簡單的 HTTP 服務(wù)器python3 -m http.server 8080然后訪問http://localhost:8080。7.2 驗(yàn)證斷電自救打開頁面后正常狀態(tài)下所有建筑燈光都是亮的左上角電網(wǎng)狀態(tài)顯示“正常”總電池電量為 100%。點(diǎn)擊“觸發(fā)斷電”按鈕后觀察頁面變化左上角電網(wǎng)狀態(tài)變?yōu)榧t色“斷電”。醫(yī)院和數(shù)據(jù)中心的燈光保持明亮顏色變?yōu)榫G色。住宅樓和商業(yè)樓的燈光變暗電池電量逐幀減少最終熄滅??傠姵仉娏堪俜直戎饾u下降。等待幾秒鐘再次點(diǎn)擊“恢復(fù)供電”所有建筑恢復(fù)正常燈光電池電量恢復(fù)為 100%。如果這些變化都能正常出現(xiàn)說明斷電自救系統(tǒng)運(yùn)行正確。7.3 調(diào)試技巧如果頁面邏輯出現(xiàn)問題可以打開瀏覽器的開發(fā)者工具F12在 Console 面板中直接調(diào)用函數(shù)來測試// 手動(dòng)觸發(fā)斷電 triggerBlackout(); // 查看某棟建筑的當(dāng)前狀態(tài) buildings.forEach(b console.log(${b.name}: ${b.status}, battery${b.batteryLevel.toFixed(1)})); // 手動(dòng)恢復(fù)供電 restorePower();Console 面板會(huì)輸出[電網(wǎng)] 斷電事件觸發(fā)啟動(dòng)應(yīng)急電源調(diào)度之類的日志方便確認(rèn)函數(shù)是否被正確調(diào)用。8. 常見問題與排查方法在實(shí)際操作中不管是用 Claude 生成代碼還是運(yùn)行 HTML 項(xiàng)目都可能遇到問題。這里整理了幾個(gè)高頻場景和對應(yīng)的排查思路。問題現(xiàn)象可能原因排查方式解決方案Claude Code 安裝報(bào)錯(cuò)error: claude native binary not installednpm 安裝不完整postinstall 腳本未執(zhí)行查看 npm 安裝日志卸載后清緩存重新安裝確認(rèn)網(wǎng)絡(luò)正常提示組織禁止了 Claude Code 訪問當(dāng)前賬號(hào)的組織后臺(tái)關(guān)閉了訂閱訪問檢查賬號(hào)類型和組織設(shè)置聯(lián)系組織管理員開啟或改用個(gè)人賬號(hào)模型名稱無法識(shí)別配置了當(dāng)前版本不支持的模型標(biāo)識(shí)查看 Claude Code 配置文檔改用官方支持的模型名稱瀏覽器打開 HTML 后黑屏Canvas 初始化失敗或 JS 報(bào)錯(cuò)打開 DevTools Console 查看報(bào)錯(cuò)確認(rèn)canvas元素 id 是否正確檢查腳本是否引用了未定義的變量點(diǎn)擊“觸發(fā)斷電”后建筑不變暗邏輯中未調(diào)用draw()方法或狀態(tài)未更新Console 執(zhí)行triggerBlackout()并輸出建筑狀態(tài)檢查調(diào)度邏輯是否修改了building.status確認(rèn)動(dòng)畫循環(huán)在使用最新狀態(tài)電池電量不減少動(dòng)畫循環(huán)中的扣電邏輯沒生效在animate()中加日志確認(rèn)isGridUp狀態(tài)正確扣電邏輯放在動(dòng)畫循環(huán)內(nèi)Claude 生成的代碼風(fēng)格混亂提示詞未明確項(xiàng)目結(jié)構(gòu)和編碼規(guī)范檢查提示詞是否包含模塊劃分說明重新生成前補(bǔ)充“請使用類封裝、函數(shù)職責(zé)單一”等約束頁面顯示亂碼HTML 文件編碼問題查看文件編碼確保meta charsetUTF-8存在于head中排在前面的是 Claude Code 的安裝問題。這類報(bào)錯(cuò)大多和 npm 包安裝不完整有關(guān)先卸載、再清緩存、再重裝能解決大部分情況。如果仍然解決不了建議去項(xiàng)目官方文檔查看最新安裝說明因?yàn)椴煌姹镜陌惭b方式可能有差異。排在后面的是 HTML 項(xiàng)目本身的運(yùn)行問題。核心思路是“先看 Console再造數(shù)據(jù)”打開開發(fā)者工具看控制臺(tái)有沒有紅色報(bào)錯(cuò)然后在 Console 里直接調(diào)用函數(shù)、修改變量觀察頁面變化。這種調(diào)試方式比反復(fù)刷新頁面更要高效。9. 最佳實(shí)踐AI 生成網(wǎng)頁項(xiàng)目的工程建議通過這次從零生成賽博城市的實(shí)踐我總結(jié)出幾條對你有實(shí)際幫助的建議。9.1 提示詞要像需求文檔一樣寫不要指望 AI 讀懂你心中模糊的想法。一句話提示詞只能得到粗糙的結(jié)果。寫提示詞時(shí)要包含項(xiàng)目背景、技術(shù)選型、數(shù)據(jù)結(jié)構(gòu)和行為邏輯。特別要描述“異常情況下的行為”比如斷電后按什么策略調(diào)度。AI 處理規(guī)則性描述比處理感受性描述可靠得多。9.2 生成后先審閱后運(yùn)行AI 生成的代碼不一定能直接跑通。運(yùn)行之前先花兩分鐘通讀代碼結(jié)構(gòu)確認(rèn)以下幾點(diǎn)關(guān)鍵函數(shù)是否完整定義比如triggerBlackout和restorePower。數(shù)據(jù)結(jié)構(gòu)和代碼調(diào)用是否匹配。是否存在明顯的基礎(chǔ)語法錯(cuò)誤。如果發(fā)現(xiàn)問題直接在對話中要求 AI 修復(fù)而不是自己手改。AI 可能比你先發(fā)現(xiàn)另一個(gè)更隱蔽的問題。9.3 使用 Git 做版本控制AI 迭代生成代碼時(shí)經(jīng)常會(huì)出現(xiàn)“改一個(gè) Bug 引入兩個(gè)新 Bug”的情況。每次讓 AI 做較大改動(dòng)前先提交一次 Git commit。這樣即使改動(dòng)失敗也能快速回滾到可用狀態(tài)。git add . git commit -m feat: 初始賽博城市版本9.4 讓 AI 解釋代碼而不是只給代碼很多新手拿到 AI 生成的代碼后直接跑跑通就完事。但真正重要的是理解代碼背后的邏輯??梢砸?AI 逐段解釋它寫的代碼或者讓它畫一個(gè)函數(shù)調(diào)用關(guān)系圖用文字描述。當(dāng)你發(fā)現(xiàn)自己能解釋清楚整個(gè)系統(tǒng)的運(yùn)行流程時(shí)這個(gè)項(xiàng)目才真正屬于你了。9.5 逐步擴(kuò)展功能不要一次要求太多如果你想給賽博城市加更多功能比如按鈕觸發(fā)不同區(qū)域的斷電、增加天氣系統(tǒng)、添加 AI 交通流模擬不要一次全部扔給 AI。一次只加一個(gè)功能運(yùn)行驗(yàn)證通過后再加下一個(gè)。逐次迭代的成功率遠(yuǎn)高于一次到位。9.6 安全與合規(guī)提醒使用 Claude Code 時(shí)注意賬號(hào)權(quán)限和遠(yuǎn)程服務(wù)的使用合規(guī)性。不要讓它執(zhí)行你不理解的命令也不要讓它訪問包含敏感信息的目錄。對于從 AI 獲取的代碼最終部署前最好有基本的安全審查特別是涉及用戶輸入、外部請求和本地文件操作的場景。10. 結(jié)合 Code 工作流拓展從單文件演示到完整項(xiàng)目如果只是做一個(gè)演示項(xiàng)目單文件 HTML 已經(jīng)足夠。但在實(shí)際開發(fā)中你可能會(huì)想把賽博城市擴(kuò)展成一個(gè)更完整的工程。這時(shí)候你就需要借助 Claude Code 的多文件編輯能力了。例如你可以請求 Claude Code 將代碼重構(gòu)為多文件結(jié)構(gòu)請把當(dāng)前的單文件 HTML 重構(gòu)為一個(gè)標(biāo)準(zhǔn)前端項(xiàng)目結(jié)構(gòu)如下 - index.html頁面入口 - css/style.css樣式文件 - js/buildings.js建筑數(shù)據(jù)定義 - js/power.js電力系統(tǒng)邏輯 - js/main.js主入口和動(dòng)畫循環(huán)Claude Code 會(huì)直接創(chuàng)建這些文件并在文件之間建立模塊引用關(guān)系。這種能力對從“寫個(gè)頁面玩一玩”到“做一個(gè)完整應(yīng)用”的跨越很有幫助。更進(jìn)一步你還可以把賽博城市畫面背后的“電力調(diào)度算法”抽象出來用在真實(shí)的物聯(lián)網(wǎng)邊緣設(shè)備管理、機(jī)房負(fù)載均衡、校車站點(diǎn)調(diào)度等場景中。項(xiàng)目本身只是一個(gè)載體真正有價(jià)值的是你在這過程中建立的系統(tǒng)思維和 AI 協(xié)作工作流。對于想繼續(xù)深入的朋友我提出三個(gè)可選的擴(kuò)展方向第一把城市規(guī)模擴(kuò)大。當(dāng)前只有 12 棟建筑你可以讓 Claude 生成 50 棟甚至 100 棟建筑并觀察 Canvas 的渲染性能。這會(huì)自然引出前端性能優(yōu)化的話題。第二引入數(shù)據(jù)可視化。把城市電力狀態(tài)繪制成實(shí)時(shí)圖表用 ECharts 或 Chart.js 展示各區(qū)域用電情況讓項(xiàng)目從“模擬器”升級成“可視化監(jiān)控平臺(tái)”。第三接入真實(shí)數(shù)據(jù)源。比如接入天氣 API雨天時(shí)城市燈光自動(dòng)調(diào)暗接入時(shí)間 API模擬晝夜更替。這套動(dòng)靜結(jié)合的模式能讓項(xiàng)目更接近真實(shí)世界的數(shù)字孿生應(yīng)用。最后再提醒一句AI 生成代碼的能力一直在進(jìn)步但工程素養(yǎng)不會(huì)自動(dòng)提升。善用工具、保持審閱習(xí)慣、理解代碼背后的設(shè)計(jì)邏輯才能把 AI 的效率真正轉(zhuǎn)化為項(xiàng)目質(zhì)量。建議收藏這篇文章下一次從零搭建 AI 創(chuàng)意網(wǎng)頁項(xiàng)目時(shí)它會(huì)是一個(gè)值得參考的起點(diǎn)。