實(shí)戰(zhàn):一天從0到1交付疾控應(yīng)急管理系統(tǒng))
“一天做完一個(gè)系統(tǒng)又一個(gè)標(biāo)題黨吧。”說實(shí)話我以前也這么想。直到我真的把需求階段和編碼階段完整跑了一遍用Hermes和Cursor這兩個(gè)AI工具把疾控應(yīng)急管理系統(tǒng)從0到1推出來才發(fā)現(xiàn)這條路的瓶頸根本不在AI寫代碼的能力而在你怎么安排需求設(shè)計(jì)和編碼的順序、怎么給AI喂上下文。這篇文章不是標(biāo)題黨而是一份真實(shí)的“1天交付”實(shí)測記錄內(nèi)容覆蓋需求設(shè)計(jì)、數(shù)據(jù)建模、后端編碼、前端生成和最終聯(lián)調(diào)的完整流程也把這一天里踩過的坑、返過工的地方原原本本寫出來。好吧先交代系統(tǒng)的最終狀態(tài)。這是一個(gè)可以本地跑起來的疾控應(yīng)急管理系統(tǒng)包含事件登記、事件分級(jí)流轉(zhuǎn)、預(yù)案管理、物資臺(tái)賬、值班排班和信息報(bào)送6個(gè)核心模塊。后端是Spring Boot 3 MyBatis Plus MySQL 8前端是Vue 3 Element Plus Pinia數(shù)據(jù)庫一共13張表前后端加起來差不多6500行代碼。從早上8點(diǎn)半開始做需求設(shè)計(jì)到晚上7點(diǎn)完成最后一輪聯(lián)調(diào)剛好一天。適合誰看如果你是準(zhǔn)備做管理系統(tǒng)類項(xiàng)目的全棧開發(fā)者或者正在糾結(jié)“AI到底能不能幫我快速搭一套可演示的業(yè)務(wù)系統(tǒng)”這篇文章能給你一份可以直接抄的作業(yè)。寫在前面的一個(gè)重要觀點(diǎn)我并不是在鼓吹“AI替代程序員”。這篇記錄真正想說的是AI輔助開發(fā)這件事成敗關(guān)鍵不在模型強(qiáng)不強(qiáng)而在你對項(xiàng)目主次怎么安排。先想清楚哪部分讓AI全權(quán)哪部分必須人來把最后一關(guān)效率差距才能真正拉開。1. 為什么選Hermes Cursor先搞清楚這倆工具各管哪一段很多人一提到“AI編程”第一反應(yīng)就是打開某個(gè)聊窗口把需求一股腦丟進(jìn)去等著AI吐出一個(gè)能運(yùn)行的項(xiàng)目。我可以負(fù)責(zé)任地說對于“從0到1做一個(gè)完整管理系統(tǒng)”這種任務(wù)這條路走不通。我的做法是把任務(wù)拆成兩半交給兩個(gè)各有側(cè)重的工具反倒在一天內(nèi)跑通了。1.1 Hermes在項(xiàng)目里扮演的角色Hermes是一個(gè)通用型的AI Agent智能體框架/平臺(tái)核心能力是你給它一個(gè)自然語言目標(biāo)它會(huì)自己拆解任務(wù)、調(diào)用工具、維護(hù)上下文并把中間產(chǎn)物保存下來。在需求設(shè)計(jì)階段我讓它當(dāng)“業(yè)務(wù)分析師架構(gòu)師”負(fù)責(zé)把“疾控應(yīng)急管理系統(tǒng)”這一句話拆成功能模塊再拆成數(shù)據(jù)表字段最后輸出建表SQL和接口清單。到編碼階段我又讓它當(dāng)“代碼生成器”按模塊批量產(chǎn)出Controller、Service、Mapper的基礎(chǔ)代碼。為什么需要這樣一個(gè)角色因?yàn)閷?shí)際開發(fā)里最消耗精力的不是“寫某一段代碼”而是“代碼之間能不能串起來”。Hermes這種Agent會(huì)把上下文保持在同一個(gè)任務(wù)流里不像普通聊天框那樣聊三頁就忘開頭。這一點(diǎn)在一天內(nèi)做完整系統(tǒng)的場景下非常關(guān)鍵——沒有連貫的上下文就沒有連貫的項(xiàng)目。1.2 Cursor在項(xiàng)目里扮演的角色Cursor是一個(gè)AI原生的代碼編輯器可以理解成“長了AI腦子的VS Code”。它負(fù)責(zé)的是“在具體代碼文件里真正動(dòng)手”改一個(gè)方法、補(bǔ)一個(gè)字段、把一個(gè)靜態(tài)頁面改成帶接口請求的Vue組件。我的用法很簡單項(xiàng)目在Cursor里打開遇到問題直接在編輯器里對話讓它定位文件、給出修改方案、應(yīng)用修改我立刻編譯驗(yàn)證循環(huán)往復(fù)。Hermes和Cursor的分工我后來總結(jié)成一句話Hermes管“方案”Cursor管“落地”。Hermes不改具體文件它的產(chǎn)出是文檔、SQL、代碼片段幫我把全局設(shè)計(jì)定住Cursor在工程里改文件讓方案變成一個(gè)能運(yùn)行的系統(tǒng)。兩者一旦混淆就會(huì)出現(xiàn)一種尷尬場面Hermes生成了大量代碼但沒法集成進(jìn)項(xiàng)目或者Cursor改了一堆文件但缺乏全局設(shè)計(jì)越改越亂。1.3 為什么不用純對話式AI一把梭我試過用純對話式AI一口氣輸出整個(gè)項(xiàng)目結(jié)果很慘。第一上下文會(huì)失控項(xiàng)目一復(fù)雜AI就開始編造不存在的表和字段第二項(xiàng)目不是單個(gè)文件而是幾十個(gè)文件的組合對話式AI給不了你“如何組織這些文件”的連貫方案第三改需求時(shí)對話式AI缺少“落地到項(xiàng)目里”的能力你需要手動(dòng)復(fù)制粘貼來回幾次就亂套。用Hermes Cursor的組合本質(zhì)上是給AI開發(fā)加了一套“流程約束”先讓Agent產(chǎn)出文檔和方案再讓編輯器AI在工程里落地。這套思路不綁定某一個(gè)特定模型我用的是本地部署的Hermes配的是模型API服務(wù)你換其他Agent框架搭配Cursor思路一樣成立。關(guān)鍵是把“規(guī)劃”和“執(zhí)行”分開讓每個(gè)AI做自己最擅長的事。2. 一天的時(shí)間線為什么需求設(shè)計(jì)必須排在編碼前面聽完這個(gè)選題我同事的第一反應(yīng)是一天做系統(tǒng)肯定全程都在寫代碼吧其實(shí)不是。真實(shí)的順序是上午先花90分鐘做需求設(shè)計(jì)和數(shù)據(jù)庫建模再花60分鐘部署工具、搭項(xiàng)目骨架真正的密集編碼集中在下午。很多人覺得“時(shí)間緊就應(yīng)該跳過設(shè)計(jì)直接寫”這恰恰是最容易被返工拖垮的做法。2.1 全天時(shí)間安排下面是我實(shí)際執(zhí)行的時(shí)間表時(shí)間段工作內(nèi)容用到的工具交付物8:30-10:00需求拆解、模塊劃分、數(shù)據(jù)模型設(shè)計(jì)Hermes需求清單、模塊清單、數(shù)據(jù)庫設(shè)計(jì)初稿10:00-11:00部署Hermes、配置Cursor、初始化項(xiàng)目骨架Hermes Cursor可運(yùn)行的空項(xiàng)目11:00-14:00后端編碼實(shí)體、接口、業(yè)務(wù)邏輯Hermes Cursor后端核心接口可調(diào)用14:00-17:00前端編碼頁面、接口對接、權(quán)限Cursor管理端主要頁面17:00-19:00聯(lián)調(diào)、修bug、狀態(tài)機(jī)完善Cursor可演示的完整系統(tǒng)這張表值得注意的不是“幾點(diǎn)做什么”而是每一步的依賴關(guān)系。沒有前一步的交付物后一步就會(huì)停擺建表SQL沒定后端實(shí)體沒法寫接口路徑?jīng)]定前端頁面沒法接登錄權(quán)限沒定頁面做完了也沒法演示。AI開發(fā)并不會(huì)改變軟件開發(fā)的基本邏輯它只是把每個(gè)環(huán)節(jié)的耗時(shí)壓縮了。所以安排一整天的工程本質(zhì)上是在安排“交付物的順序”。2.2 為什么“先跑通空項(xiàng)目”優(yōu)先級(jí)這么高上午10點(diǎn)到11點(diǎn)我的任務(wù)是部署Hermes、配置Cursor以及初始化一個(gè)能運(yùn)行的空項(xiàng)目骨架。這里我給自己定的硬性要求是11點(diǎn)之前新建項(xiàng)目的首頁必須在瀏覽器里能打開后端健康檢查接口必須能通。因?yàn)楹罄m(xù)所有AI生成的代碼都需要一個(gè)能運(yùn)行的環(huán)境去驗(yàn)證。骨架沒搭好AI生成再多代碼你也沒法立刻看到效果錯(cuò)誤就會(huì)不斷疊加。這個(gè)空項(xiàng)目我把它叫作“驗(yàn)證腳手架”。它不需要包含任何業(yè)務(wù)代碼但要包含完整的依賴配置、統(tǒng)一返回結(jié)果類、異常處理器、MyBatis Plus配置和前端的基礎(chǔ)布局。有了這個(gè)腳手架Hermes生成的后端代碼可以直接扔進(jìn)對應(yīng)的包路徑里Cursor生成的前端頁面可以直接替換掉腳手架里的占位組件AI的產(chǎn)出才能被快速驗(yàn)證、快速迭代。如果不先做這一步后面所有AI生成的代碼都只是在“紙面運(yùn)行”效率會(huì)大打折扣。2.3 把接口規(guī)范提前釘死在設(shè)計(jì)階段需求設(shè)計(jì)可以快但不代表字段和接口規(guī)范可以含糊。在上午的需求設(shè)計(jì)階段除了生成模塊清單和SQL我還做了第二件事讓Hermes產(chǎn)出一份接口路徑規(guī)范。比如事件模塊統(tǒng)一以/api/event開頭列表用POST /api/event/page新增用POST /api/event狀態(tài)變更用PUT /api/event/{id}/status返回格式統(tǒng)一是ResultT。這個(gè)規(guī)范在前端開發(fā)時(shí)幫我省下了大量溝通成本。這個(gè)動(dòng)作在傳統(tǒng)開發(fā)里可能要開一次接口評審會(huì)但在AI輔助流程里只是給Hermes的提示詞里多了一句“請一并輸出接口路徑清單使用RESTful風(fēng)格”。然而正是這一句話決定了下午前端對接時(shí)是順暢還是崩潰。接口規(guī)范一旦不定前端AI和后端AI就會(huì)各寫各的最后聯(lián)調(diào)階段一定會(huì)出現(xiàn)“字段對不上、路徑對不上、返回格式對不上”的三重災(zāi)難。3. 需求設(shè)計(jì)怎樣把“疾控應(yīng)急管理系統(tǒng)”拆成AI能懂的模塊需求設(shè)計(jì)這個(gè)環(huán)節(jié)在傳統(tǒng)流程里至少要開兩三次會(huì)但在AI輔助下我把它壓縮成一個(gè)提示詞加幾輪追問。不過壓縮的是時(shí)間不是思考。恰恰因?yàn)锳I產(chǎn)出的速度太快人要做的那幾次糾偏就顯得更加關(guān)鍵。3.1 讓Hermes產(chǎn)出模塊清單的提示詞我給Hermes的第一條提示詞是這樣寫的你是一名公共衛(wèi)生應(yīng)急領(lǐng)域的系統(tǒng)分析師。我需要你幫我做需求設(shè)計(jì)。 項(xiàng)目疾控應(yīng)急管理系統(tǒng)。 核心業(yè)務(wù)對突發(fā)公共衛(wèi)生事件進(jìn)行登記、分級(jí)、流轉(zhuǎn)處置、應(yīng)急物資調(diào)配、預(yù)案管理和值班管理。 目標(biāo)用戶疾控中心業(yè)務(wù)人員、應(yīng)急辦管理人員、中心領(lǐng)導(dǎo)。 請輸出 1. 功能模塊清單 2. 每個(gè)模塊下的核心子功能 3. 涉及的實(shí)體對象和關(guān)鍵字段建議。 約束 - 面向省級(jí)疾控中心場景多科室、多角色協(xié)作 - 需要有事件全流程狀態(tài)管理 - 需要數(shù)據(jù)權(quán)限不同角色看到的數(shù)據(jù)范圍不同 - 不需要復(fù)雜的財(cái)務(wù)和審批流。注意提示詞里我特意寫了兩類信息一類是業(yè)務(wù)范圍即“吃什么”一類是約束條件即“不吃什么”。這是AI能給出準(zhǔn)確需求設(shè)計(jì)的關(guān)鍵。如果你只寫“幫我設(shè)計(jì)一個(gè)應(yīng)急管理系統(tǒng)”AI會(huì)給出一堆大而全但沒法落地的功能比如“智慧預(yù)警”“大數(shù)據(jù)分析”這些對一天可交付的項(xiàng)目來說全是坑。約束寫得越清楚AI產(chǎn)出的模塊越克制后面寫代碼時(shí)就越不容易跑偏。3.2 生成的模塊清單和核心表結(jié)構(gòu)Hermes在幾分鐘內(nèi)給出的模塊清單基本覆蓋了核心業(yè)務(wù)。它列出的模塊包括應(yīng)急事件模塊負(fù)責(zé)事件登記、事件分級(jí)、狀態(tài)流轉(zhuǎn)和查詢預(yù)案管理模塊負(fù)責(zé)預(yù)案錄入、版本管理和啟動(dòng)記錄物資管理模塊負(fù)責(zé)物資臺(tái)賬、出入庫記錄和庫存預(yù)警值班管理模塊負(fù)責(zé)排班、值班日志和交接班記錄信息報(bào)送模塊負(fù)責(zé)報(bào)送單生成、逐級(jí)上報(bào)和處置反饋系統(tǒng)管理模塊負(fù)責(zé)用戶、角色、菜單權(quán)限和操作日志?;谶@份清單我繼續(xù)讓Hermes產(chǎn)出數(shù)據(jù)庫設(shè)計(jì)。它最終生成了13張表其中最核心的一張是應(yīng)急事件表我貼出來CREATE TABLE emergency_event ( id BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT 事件ID, event_code VARCHAR(32) NOT NULL COMMENT 事件編號(hào), event_name VARCHAR(128) NOT NULL COMMENT 事件名稱, event_type VARCHAR(32) NOT NULL COMMENT 事件類型, event_level TINYINT NOT NULL COMMENT 事件等級(jí):1一般 2較大 3重大 4特別重大, event_status TINYINT NOT NULL DEFAULT 1 COMMENT 狀態(tài):1待核實(shí) 2核實(shí)中 3處置中 4已結(jié)案, report_time DATETIME NOT NULL COMMENT 報(bào)告時(shí)間, reporter VARCHAR(64) NULL COMMENT 報(bào)告人, reporter_phone VARCHAR(20) NULL COMMENT 報(bào)告人電話, location VARCHAR(255) NULL COMMENT 事發(fā)地點(diǎn), description TEXT NULL COMMENT 事件描述, org_code VARCHAR(32) NULL COMMENT 所屬區(qū)域編碼, create_by BIGINT NULL COMMENT 創(chuàng)建人ID, create_time DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT 創(chuàng)建時(shí)間, update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 更新時(shí)間, KEY idx_status (event_status), KEY idx_report_time (report_time) ) COMMENT 應(yīng)急事件表;這個(gè)表生成后基本夠用但我做了兩處補(bǔ)充。第一加了org_code字段因?yàn)楹竺孀鰯?shù)據(jù)權(quán)限過濾要用它區(qū)分“這個(gè)事件屬于哪個(gè)轄區(qū)”。第二給狀態(tài)和報(bào)告時(shí)間加了索引因?yàn)閼?yīng)急事件查詢基本都會(huì)按這兩個(gè)條件過濾。其他12張表包括預(yù)案表、物資表、出入庫明細(xì)表、值班表、報(bào)送單表、用戶角色表等我基本沒做大改直接放進(jìn)了初始化腳本。3.3 人必須做的糾偏AI會(huì)“想當(dāng)然”的三個(gè)例子但這里要說一個(gè)真實(shí)問題AI生成的需求設(shè)計(jì)表面合理但有幾個(gè)地方是“想當(dāng)然”的必須人工修正。第一AI默認(rèn)所有列表都是單表查詢。實(shí)際上應(yīng)急事件列表往往要關(guān)聯(lián)用戶表顯示處理人姓名關(guān)聯(lián)報(bào)送單顯示最新處置進(jìn)度。如果一開始沒提醒它后面接口會(huì)越寫越復(fù)雜甚至要推翻重來。我現(xiàn)在的做法是在提示詞里約定“列表查詢需要支持多表關(guān)聯(lián)返回VO對象”讓它在設(shè)計(jì)階段就把這個(gè)因素考慮進(jìn)去。第二AI不會(huì)主動(dòng)考慮邏輯刪除。疾控應(yīng)急事件作為業(yè)務(wù)數(shù)據(jù)不能物理刪除只能邏輯刪除。我必須在提示詞里明確“所有業(yè)務(wù)表需要邏輯刪除字段”并讓Hermes在SQL里統(tǒng)一補(bǔ)上deleted字段。這條約束如果漏了后面刪除接口就會(huì)直接把記錄抹掉在真實(shí)業(yè)務(wù)場景下是絕對不允許的。第三AI對“數(shù)據(jù)權(quán)限”的理解容易停留在“有權(quán)限就能訪問模塊”的層面。在真實(shí)應(yīng)急場景里區(qū)縣疾控中心只能看本轄區(qū)事件省級(jí)中心才能看全部。所以我在表設(shè)計(jì)時(shí)增加了org_code把數(shù)據(jù)范圍的維度提前落到表結(jié)構(gòu)里。這些糾偏花了我大概20分鐘。如果跳過這一步直接讓AI寫代碼后面改起來就不是20分鐘能解決的問題了。4. 后端編碼從建表SQL到業(yè)務(wù)接口的AI協(xié)作節(jié)奏需求定完建表SQL有了數(shù)據(jù)庫13張表全部建好之后就進(jìn)入了全天工作量最大的后端編碼階段。這個(gè)階段我又拆成了三步先生成基礎(chǔ)代碼再寫復(fù)雜業(yè)務(wù)最后做接口自測。4.1 實(shí)體和基礎(chǔ)CRUD批量生成的正確姿勢拿到建表SQL之后傳統(tǒng)做法是一個(gè)表一個(gè)Controller、Service、Mapper地去寫非常機(jī)械。我把建表語句直接丟給Hermes讓它按MyBatis Plus規(guī)范生成實(shí)體類和基礎(chǔ)CRUD接口。這里的關(guān)鍵是提示詞里要明確項(xiàng)目規(guī)范否則AI生成出來的代碼風(fēng)格會(huì)五花八門。我當(dāng)時(shí)的規(guī)范約束是這些統(tǒng)一返回結(jié)果類型ResultT、統(tǒng)一異常處理、邏輯刪除字段用TableLogic注解、主鍵用雪花算法、時(shí)間字段用LocalDateTime。把這些規(guī)范寫成一個(gè)約束段落放進(jìn)提示詞AI生成的代碼風(fēng)格就會(huì)統(tǒng)一。我抽查了幾個(gè)生成出來的實(shí)體類基本符合預(yù)期。比如事件實(shí)體里的關(guān)鍵字段Data TableName(emergency_event) public class EmergencyEvent { TableId(type IdType.ASSIGN_ID) private Long id; private String eventCode; private String eventName; private String eventType; private Integer eventLevel; private Integer eventStatus; private LocalDateTime reportTime; private String reporter; private String reporterPhone; private String location; private String description; private String orgCode; TableLogic private Integer deleted; private Long createBy; private LocalDateTime createTime; private LocalDateTime updateTime; }批量生成的Controller同樣中規(guī)中矩分頁查詢、新增、修改、刪除、詳情五個(gè)接口一次給全。這個(gè)階段的目標(biāo)不是炫技而是把重復(fù)勞動(dòng)快速做完給后面的復(fù)雜業(yè)務(wù)留出時(shí)間。基礎(chǔ)代碼這種活A(yù)I最擅長人也最不該在它身上浪費(fèi)太多時(shí)間。4.2 復(fù)雜查詢和狀態(tài)流轉(zhuǎn)這部分必須人盯基礎(chǔ)CRUD生成完我開始處理真正體現(xiàn)業(yè)務(wù)價(jià)值的兩個(gè)部分一個(gè)是應(yīng)急事件的多條件分頁查詢一個(gè)是事件狀態(tài)流轉(zhuǎn)。多條件分頁查詢這種帶動(dòng)態(tài)條件的邏輯我讓Hermes生成了一段Wrapper查詢Override public PageEmergencyEventVO pageEvents(EventQuery query) { LambdaQueryWrapperEmergencyEvent wrapper new LambdaQueryWrapper(); wrapper.eq(StringUtils.hasText(query.getEventType()), EmergencyEvent::getEventType, query.getEventType()) .eq(query.getEventLevel() ! null, EmergencyEvent::getEventLevel, query.getEventLevel()) .eq(query.getEventStatus() ! null, EmergencyEvent::getEventStatus, query.getEventStatus()) .like(StringUtils.hasText(query.getKeyword()), EmergencyEvent::getEventName, query.getKeyword()) .eq(StringUtils.hasText(query.getOrgCode()), EmergencyEvent::getOrgCode, query.getOrgCode()) .orderByDesc(EmergencyEvent::getReportTime); return eventMapper.selectPage(new Page(query.getPageNum(), query.getPageSize()), wrapper); }這段代碼本身不難但里面藏著一個(gè)容易遺漏的邏輯數(shù)據(jù)權(quán)限。當(dāng)前用戶是區(qū)縣角色時(shí)查詢條件里必須強(qiáng)制拼上org_code 當(dāng)前用戶轄區(qū)。這個(gè)條件是動(dòng)態(tài)拼進(jìn)去的普通開發(fā)很容易忘了在列表頁加導(dǎo)致某個(gè)區(qū)縣的人看到了全省的事件這在應(yīng)急場景下是嚴(yán)重的數(shù)據(jù)越權(quán)。我把這個(gè)邏輯單拎出來寫成了一個(gè)DataScopeHelper所有列表查詢統(tǒng)一走這個(gè)Helper而不是在每個(gè)Service里各寫各的。狀態(tài)流轉(zhuǎn)這里我也提醒一句不要直接生成“誰都能改狀態(tài)”的接口。事件狀態(tài)不是隨便跳的已結(jié)案不能退回待核實(shí)處置中不能跳過核實(shí)直接結(jié)案。我讓Hermes生成一個(gè)枚舉和狀態(tài)機(jī)校驗(yàn)方法public enum EventStatus { PENDING(1, 待核實(shí)), VERIFYING(2, 核實(shí)中), HANDLING(3, 處置中), CLOSED(4, 已結(jié)案); private final int code; private final String text; EventStatus(int code, String text) { this.code code; this.text text; } }然后把合法的流轉(zhuǎn)關(guān)系放在一個(gè)Map里每次變更狀態(tài)前先校驗(yàn)。這個(gè)邏輯代碼量很少但它決定了一個(gè)應(yīng)急系統(tǒng)能不能用。如果狀態(tài)可以亂跳后面的結(jié)案統(tǒng)計(jì)、處置時(shí)限考核就全廢了。AI能幫你寫80%的代碼但這種業(yè)務(wù)規(guī)則人是必須親自確認(rèn)的。4.3 接口自測讓AI順手生成一份最小化測試數(shù)據(jù)后端寫完我遇到一個(gè)很現(xiàn)實(shí)的問題接口邏輯對不對得拿數(shù)據(jù)去測。人工造數(shù)據(jù)實(shí)在太慢我讓Hermes寫了一個(gè)CommandLineRunner在應(yīng)用啟動(dòng)時(shí)自動(dòng)插入測試數(shù)據(jù)5名用戶、3個(gè)角色、2個(gè)事件、若干物資記錄。這樣每次啟動(dòng)應(yīng)用都有現(xiàn)成的數(shù)據(jù)可以點(diǎn)擊驗(yàn)證。這個(gè)做法極大加快了聯(lián)調(diào)速度但有一個(gè)坑測試數(shù)據(jù)會(huì)自動(dòng)污染庫表。我的處理方式是在配置里加了一個(gè)開關(guān)本地開發(fā)和演示時(shí)才開啟生產(chǎn)環(huán)境絕不帶出去。類似這種“開發(fā)輔助代碼”AI是很樂于生成的但開工前就要約定好隔離方式否則測試數(shù)據(jù)混進(jìn)正式環(huán)境后面清理起來非常痛苦。5. 前端頁面Cursor幫我寫出了80%的Vue組件后端接口有了前端頁面就進(jìn)入了密集生產(chǎn)階段。這個(gè)階段的主工具從Hermes換成了Cursor原因很簡單前端頁面需要頻繁改文件、看效果、再改文件Cursor這種和編輯器深度綁定的AI效率最高。一次對話改完立刻能在瀏覽器里刷新驗(yàn)證反饋回路非常短。5.1 頁面規(guī)劃和組件拆解我先把后臺(tái)管理端的頁面清單列出來登錄頁、系統(tǒng)布局、事件管理列表頁、事件新增/詳情頁、預(yù)案管理頁、物資管理頁、值班管理頁、信息報(bào)送頁、用戶管理頁、角色管理頁差不多10個(gè)頁面。然后讓Cursor按“布局組件、列表頁、表單頁”三種模式分別生成再逐個(gè)替換成真實(shí)接口。頁面規(guī)劃時(shí)有一個(gè)容易被忽略的技巧先讓Cursor生成一個(gè)統(tǒng)一的API請求封裝把Axios實(shí)例、請求攔截器、Token攜帶、錯(cuò)誤提示都處理好。所有頁面共用這個(gè)封裝而不是讓每個(gè)頁面自己發(fā)請求。這一步看似不起眼但它是前端代碼風(fēng)格統(tǒng)一的關(guān)鍵。沒有統(tǒng)一封裝每個(gè)頁面的請求代碼就會(huì)各寫各的后面維護(hù)起來非常痛苦。5.2 對話式生成一個(gè)事件管理頁當(dāng)時(shí)讓Cursor生成事件列表頁我的指令是在src/views/event/index.vue里生成一個(gè)事件管理頁面用Element Plus的el-table展示事件列表包含事件編號(hào)、事件名稱、事件等級(jí)、事件狀態(tài)、報(bào)告時(shí)間、操作列支持分頁和狀態(tài)篩選操作列包含“詳情”和“流轉(zhuǎn)”按鈕調(diào)用/api/event/page接口。Cursor生成的頁面我只做了少量修改就接上了接口核心代碼結(jié)構(gòu)類似這樣template div classpage-container el-card shadownever el-form :inlinetrue :modelquery el-form-item label事件名稱 el-input v-modelquery.keyword placeholder請輸入關(guān)鍵詞 clearable / /el-form-item el-form-item label事件狀態(tài) el-select v-modelquery.eventStatus placeholder全部 clearable el-option v-foritem in statusOptions :keyitem.value :labelitem.label :valueitem.value / /el-select /el-form-item el-form-item el-button typeprimary clickloadData查詢/el-button /el-form-item /el-form el-table :datatableData v-loadingloading border stripe el-table-column propeventCode label事件編號(hào) min-width140 / el-table-column propeventName label事件名稱 min-width200 / el-table-column propeventLevel label等級(jí) width80 template #default{ row } el-tag :typelevelType[row.eventLevel]{{ levelText[row.eventLevel] }}/el-tag /template /el-table-column el-table-column propeventStatus label狀態(tài) width90 template #default{ row } el-tag :typestatusType[row.eventStatus]{{ statusText[row.eventStatus] }}/el-tag /template /el-table-column el-table-column propreportTime label報(bào)告時(shí)間 width160 / el-table-column label操作 width150 fixedright template #default{ row } el-button link typeprimary clickopenDetail(row)詳情/el-button el-button link typewarning clickopenFlow(row)流轉(zhuǎn)/el-button /template /el-table-column /el-table el-pagination v-model:current-pagequery.pageNum v-model:page-sizequery.pageSize :totaltotal layouttotal, prev, pager, next current-changeloadData / /el-card /div /template這里特別想提醒一點(diǎn)AI生成的前端頁面默認(rèn)情況下不會(huì)處理狀態(tài)枚舉的映射。事件狀態(tài)在數(shù)據(jù)庫里是1、2、3、4這樣的數(shù)字如果頁面上直接顯示數(shù)字用戶根本看不懂。我讓Cursor同時(shí)生成了statusText、statusType這類映射對象再用el-tag把狀態(tài)渲染成不同顏色的標(biāo)簽。這個(gè)細(xì)節(jié)雖然小但決定了頁面是“能看”還是“能用”。5.3 接口對接和權(quán)限按鈕處理前端頁面接后端接口時(shí)最容易出問題的不是請求本身而是字段名對不上。AI生成的前端代碼可能默認(rèn)后端返回的是camelCase字段而后端實(shí)體類某些字段是下劃線風(fēng)格兩者一錯(cuò)位頁面上全是undefined。我的解決辦法是在接口封裝層統(tǒng)一做字段映射或者在提示詞里一開始就規(guī)定“所有后端返回字段使用駝峰命名”讓兩邊從一開始就保持一致。經(jīng)過這一天的實(shí)操我更推薦后者與其事后轉(zhuǎn)換不如源頭統(tǒng)一。權(quán)限按鈕的處理也值得單獨(dú)說。應(yīng)急系統(tǒng)的操作按鈕不是每個(gè)人都可見普通業(yè)務(wù)員能看到“上報(bào)”按鈕科室負(fù)責(zé)人能看到“核實(shí)”按鈕領(lǐng)導(dǎo)能看到“結(jié)案”按鈕。Cursor可以在按鈕上加一個(gè)v-permission指令由權(quán)限指令根據(jù)當(dāng)前用戶的按鈕權(quán)限列表決定是否渲染。這個(gè)能力是我在生成頁面時(shí)通過提示詞提前約定好的后面所有頁面統(tǒng)一復(fù)用避免每個(gè)頁面各寫各的判斷邏輯。6. 疾控應(yīng)急系統(tǒng)里最容易翻車的兩個(gè)業(yè)務(wù)點(diǎn)狀態(tài)流轉(zhuǎn)和數(shù)據(jù)權(quán)限整天的開發(fā)里如果說有哪個(gè)環(huán)節(jié)讓我感覺“差點(diǎn)翻車”那一定是狀態(tài)流轉(zhuǎn)和數(shù)據(jù)權(quán)限。這兩個(gè)問題AI幾乎不可能自己意識(shí)到必須由懂業(yè)務(wù)的人主動(dòng)提出來然后在需求設(shè)計(jì)階段就定好規(guī)則。6.1 事件狀態(tài)機(jī)AI默認(rèn)只會(huì)做增刪改查我第一次讓Hermes做事件狀態(tài)管理時(shí)它生成的是一個(gè)簡單的updateStatus接口誰都可以調(diào)用傳什么狀態(tài)就改成什么狀態(tài)。從技術(shù)上這沒錯(cuò)但從業(yè)務(wù)上這是災(zāi)難。如果一條“已結(jié)案”的事件被誤操作改回“待核實(shí)”后面的處置時(shí)限統(tǒng)計(jì)、結(jié)案報(bào)表就全亂了。我把狀態(tài)流轉(zhuǎn)定義成“只允許從當(dāng)前狀態(tài)經(jīng)過合法動(dòng)作進(jìn)入下一狀態(tài)”核心流轉(zhuǎn)關(guān)系如下當(dāng)前狀態(tài)允許的動(dòng)作目標(biāo)狀態(tài)待核實(shí)核實(shí)核實(shí)中待核實(shí)誤報(bào)關(guān)閉已關(guān)閉核實(shí)中啟動(dòng)處置處置中處置中結(jié)案已結(jié)案處置中升級(jí)上報(bào)已上報(bào)此外狀態(tài)之間還必須記錄操作人和操作時(shí)間所以我讓Hermes補(bǔ)了一張狀態(tài)流轉(zhuǎn)日志表。加入之后領(lǐng)導(dǎo)在詳情頁可以看到一條事件的完整時(shí)間線幾點(diǎn)幾分誰做了核實(shí)幾點(diǎn)幾分誰啟動(dòng)了處置。這在應(yīng)急管理場景里非常關(guān)鍵。所以我建議凡是涉及“流程”的項(xiàng)目哪怕再簡單都要讓AI先生成“狀態(tài)動(dòng)作校驗(yàn)”三件套而不是簡單生成一個(gè)改狀態(tài)的接口。6.2 數(shù)據(jù)權(quán)限應(yīng)急場景下“誰看誰的數(shù)據(jù)”不能一刀切疾控應(yīng)急系統(tǒng)的用戶按層級(jí)分為省級(jí)中心、市級(jí)中心、區(qū)縣中心。默認(rèn)規(guī)則是區(qū)縣中心只能看本轄區(qū)事件市級(jí)中心能看本市所有區(qū)縣省級(jí)中心能看全部。這就是數(shù)據(jù)權(quán)限問題。如果只用簡單的RBAC做權(quán)限控制它能控制“這個(gè)角色能不能訪問事件模塊”但控制不了“這個(gè)用戶能看哪幾條事件記錄”后者必須靠數(shù)據(jù)權(quán)限過濾實(shí)現(xiàn)。我的做法是在用戶表里存org_code在事件表里存事發(fā)地對應(yīng)的org_code查詢時(shí)根據(jù)當(dāng)前用戶的行政區(qū)劃級(jí)別動(dòng)態(tài)拼接條件。這個(gè)邏輯對AI來說可以一次性生成但它不是一個(gè)自動(dòng)出現(xiàn)的需求。如果你不告訴AI“應(yīng)急系統(tǒng)需要按管轄層級(jí)控制數(shù)據(jù)可見范圍”AI交付的版本就一定是所有角色看到同一份數(shù)據(jù)。這也是我反復(fù)強(qiáng)調(diào)不要在需求設(shè)計(jì)階段省時(shí)間的原因——這個(gè)階段20分鐘的投入有可能幫你省掉寫完后一次大返工。7. Hermes部署與使用Windows環(huán)境下實(shí)測的幾個(gè)坑這一章寫給第一次接觸Hermes的讀者。我把自己在Windows本機(jī)部署和使用Hermes的過程以及當(dāng)天遇到的幾個(gè)典型問題整理一下。需要說明的是具體命令和參數(shù)以你使用的版本和官方文檔為準(zhǔn)但排查思路基本是通用的。7.1 部署流程和模型配置部署這類Agent框架/平臺(tái)流程通常是固定的先檢查本機(jī)環(huán)境主要看Python或Node版本是否滿足要求然后下載或拉取安裝包在項(xiàng)目目錄里安裝依賴接著配置模型的接入方式也就是模型服務(wù)的API地址和密鑰最后啟動(dòng)服務(wù)在瀏覽器或客戶端里開始對話。當(dāng)天我在自己本機(jī)操作時(shí)大致就是這個(gè)順序。裝依賴的過程花了一點(diǎn)時(shí)間整體不算復(fù)雜。配模型的時(shí)候有個(gè)細(xì)節(jié)值得注意不同模型對上下文長度和工具調(diào)用的支持不一樣部署之后第一件事應(yīng)該是先跑一個(gè)最簡單的測試對話確認(rèn)它能正常返回結(jié)果而不是直接丟一個(gè)需求任務(wù)過去。如果模型本身沒配好后面所有步驟都白搭。7.2 實(shí)際遇到的三類問題第一類是PowerShell執(zhí)行策略問題。在Windows上如果用了腳本啟動(dòng)服務(wù)經(jīng)常會(huì)遇到“無法加載文件因?yàn)樵诖讼到y(tǒng)上禁止運(yùn)行腳本”之類的報(bào)錯(cuò)。這個(gè)問題很好解決用管理員身份打開PowerShell執(zhí)行一次Set-ExecutionPolicy RemoteSigned再重試啟動(dòng)腳本。第二類是端口占用。Agent服務(wù)默認(rèn)端口可能被其他程序占了啟動(dòng)時(shí)會(huì)報(bào)端口沖突。我的做法是啟動(dòng)前先查一下端口占用情況被占用了就換一個(gè)端口不要硬剛。第三類是中文亂碼。如果Agent生成的文檔或日志在Windows終端里顯示亂碼大概率是終端編碼問題。把終端的代碼頁切到UTF-8或者在啟動(dòng)命令里設(shè)置編碼參數(shù)問題一般就能解決。7.3 提示詞交互的實(shí)操技巧使用Hermes這類Agent和普通AI聊天的最大區(qū)別是它有一個(gè)“任務(wù)”的概念。你可以把一整天的需求設(shè)計(jì)變成一個(gè)任務(wù)讓它分步驟執(zhí)行中間會(huì)產(chǎn)出文檔、SQL、代碼片段。為了讓任務(wù)執(zhí)行得穩(wěn)我有幾個(gè)小技巧。第一每個(gè)任務(wù)的開頭先交代“角色目標(biāo)約束”不要邊聊邊補(bǔ)因?yàn)檠a(bǔ)丁式對話會(huì)讓上下文越來越亂。第二如果任務(wù)里需要AI產(chǎn)出多個(gè)文件把文件清單和命名規(guī)則一次說清楚比如“實(shí)體類放com.example.entity包Controller放com.example.controller包”。第三如果AI中途給出了不滿意結(jié)果不要直接說“重寫”而是告訴它“哪一部分有問題改成什么方向”這樣它能保留正確的部分而不是推倒重來。提示Agent的生產(chǎn)結(jié)果一定要讓它在任務(wù)結(jié)束時(shí)匯總成一份清單比如“輸出本次生成的SQL文件清單、代碼文件清單”。這份清單方便你逐個(gè)核對也方便后續(xù)交給Cursor去落地。沒有清單AI生成的中間產(chǎn)物就會(huì)像散落一地的零件很難組織起來。8. 一天結(jié)束后的復(fù)盤時(shí)間都花在了哪里項(xiàng)目跑起來之后我做了一個(gè)效率復(fù)盤。這里把AI輔助開發(fā)和傳統(tǒng)方式的耗時(shí)對比放出來也把必須人盯的環(huán)節(jié)說清楚方便后面再做類似項(xiàng)目時(shí)有個(gè)參考。8.1 效率對比拿疾控應(yīng)急管理系統(tǒng)來說如果按傳統(tǒng)開發(fā)方式需求設(shè)計(jì)加原型通常要3到5天前后端聯(lián)調(diào)再加一周很正常。而AI輔助下的實(shí)際耗時(shí)分布大概是環(huán)節(jié)傳統(tǒng)開發(fā)耗時(shí)AI輔助實(shí)際耗時(shí)主要省在哪里需求梳理和模塊設(shè)計(jì)2-3天2小時(shí)AI生成初稿人只做糾偏數(shù)據(jù)庫設(shè)計(jì)0.5-1天30分鐘建表SQL直接生成后端基礎(chǔ)CRUD2-3天3小時(shí)批量化生成實(shí)體和接口前端全部頁面4-5天4小時(shí)Cursor批量生成Vue組件聯(lián)調(diào)和修復(fù)2-3天2.5小時(shí)接口規(guī)范統(tǒng)一后問題大減為什么能省這么多核心在于大部分重復(fù)勞動(dòng)的“代碼骨架”被AI包掉了人只需要做三件事在需求階段把業(yè)務(wù)規(guī)則定清楚在編碼階段把復(fù)雜邏輯確認(rèn)好在聯(lián)調(diào)階段盯著字段和狀態(tài)流轉(zhuǎn)。剩下的重復(fù)代碼AI做得又快又不容易疲勞。8.2 必須人工把關(guān)的三個(gè)環(huán)節(jié)但我也要說清楚不是所有環(huán)節(jié)AI都省時(shí)間。至少有三個(gè)環(huán)節(jié)人必須親自盯否則后面一定會(huì)返工。第一個(gè)是狀態(tài)流轉(zhuǎn)和業(yè)務(wù)規(guī)則。AI默認(rèn)的思維是“可修改”而業(yè)務(wù)要求是“可控制”這兩者之間的差距需要人來填。第二個(gè)是數(shù)據(jù)權(quán)限。它不是頁面上的一個(gè)功能而是貫穿所有查詢的橫切邏輯AI不會(huì)主動(dòng)考慮到組織層級(jí)和數(shù)據(jù)范圍。第三個(gè)是接口字段的一致性。后端返回什么字段、前端用什么字段必須在一開始就約定好不然聯(lián)調(diào)階段會(huì)反復(fù)出現(xiàn)“頁面顯示undefined”的問題。8.3 后續(xù)擴(kuò)展方向一天做完的版本定位是“可演示、可驗(yàn)證、可繼續(xù)迭代”的基線版本不是生產(chǎn)級(jí)系統(tǒng)。如果要把這個(gè)系統(tǒng)繼續(xù)往前推我大概會(huì)按這個(gè)順序擴(kuò)展第一步把文件上傳和附件管理補(bǔ)上比如事件現(xiàn)場照片和處置報(bào)告第二步接入大屏展示把事件分布、物資庫存、值班情況投到指揮中心的大屏第三步加上消息通知事件狀態(tài)變化時(shí)通過短信或站內(nèi)信提醒相關(guān)人員第四步再做一套移動(dòng)端H5方便現(xiàn)場人員用手機(jī)上報(bào)事件。每一層擴(kuò)展都可以沿用當(dāng)天的AI協(xié)作模式先讓Agent出方案再讓Cursor改代碼。如果讓我再做一遍這類項(xiàng)目我會(huì)在需求設(shè)計(jì)階段再多留半小時(shí)。設(shè)計(jì)階段省下的時(shí)間后面幾乎都會(huì)以返工的方式還回去。另一個(gè)經(jīng)驗(yàn)是下午四點(diǎn)半之后堅(jiān)決不開新功能所有時(shí)間留給聯(lián)調(diào)和修bug。AI能幫你在一天內(nèi)把系統(tǒng)“寫完”但“寫完”和“能用”之間隔著的那層細(xì)節(jié)——狀態(tài)能不能走通、權(quán)限遮沒遮對、按鈕點(diǎn)擊有沒有反應(yīng)——永遠(yuǎn)需要一雙人眼去盯。這也是AI開發(fā)這件事最真實(shí)的邊界。