最近刚把Vibe-coding系列任务的最后一个Task5交掉心里一块石头落了地。这个系列前四期都是每次一个小主题做做小工具、练练prompt感觉像在玩拼图。但Task5的题目写得很直白——“收官之战项目产出”。它不是让你再堆一个新功能而是把前面所有零散的尝试收拢成一个真正能交付、能给别人用的东西。我最后拿出来的项目叫“随手计划”听起来像个待办清单但核心逻辑完全不同你直接输入“下周三下午三点提醒我给设计稿回邮件重要”它会自动把这句话拆成结构化任务生成带截止时间、优先级和标签的卡片然后你自己决定要不要改。这篇文章我把这次产出的完整过程、思路和踩过的坑都写下来不管是还在观望Vibe-coding还是已经上手准备做个正经项目的人应该都能从里头摸到点门道。1. 把“收官之战”读懂Task5到底在考验什么1.1 为什么偏偏叫“收官之战”参加这种以Vibe-coding为主题的系列实战很多人会误以为重点在于“让AI写代码快”于是前面几期都沉浸在“自然语言生成小函数”的爽感里。到了收官任务大家普遍的心态是反正AI这么能写那我就再做一个更酷的交互效果、再加一个动画、再堆一个图表——结果很容易做成一个“功能很多但要啥没啥”的半成品。Task5的表述里藏着两层含义。第一层是“收官”意思是整个系列要画句号了你的产出应该代表这个阶段能力的上限第二层是“项目产出”而不是“功能Demo”。这两个词一对比就很扎心Demo追求的是“看起来亮眼”项目追求的是“拿起来能用”。我后来在最终复盘里写了一句如果这个工具我只自己玩那叫Demo如果我能让别人也用它解决一天里的真实问题那才叫产出。1.2 我为什么选“自然语言待办面板”而不是做花哨的东西收官任务消息一出一起参加的人里冒出来好几个方向有人要做AI生成PPT有人要做自动记周报的机器人还有人要做一个能聊天查电影信息的小程序。我本来也动了做“一副赛博朋克风格的数据大屏”的念头但冷静下来算了一笔账。Vibe-coding擅长的是“快速把脑子里的想法变成可见的界面和逻辑”但它的短板也很清晰只要涉及复杂的业务规则、海量数据建模、精确到像素的视觉还原AI生成的内容就需要你花双倍时间返工。一个待办面板功能边界非常清晰输入一段话、解析成结构、展示卡片、支持增删改。这恰恰是Vibe-coding的甜蜜区——用自然语言去驱动AI写“胶水代码”而真正的智能核心放在大模型解析上这个思路比例符合工具定位。另一个选择它的理由是待办工具每个人都在用马上能验证“好不好用”。我把初始版本丢给两位经常拖延的朋友用了一天他们反馈“居然真的能看懂人话”那一刻我才觉得这个产出是成立的。1.3 先定四条铁律避免后期失控在写第一行代码之前我给项目定了四条规矩本地优先。所有数据存在浏览器本地不上云、不注册账号打开就能用。自然语言是唯一入口。可以手动点按钮但最核心的交互永远是“公司一句话任务自动生成”。保留人工确认的主动权。AI解析出的任务可以不完美但必须让我能一键修改。不追求功能多追求闭环完整。从“输入一句话”到“任务出现在列表里”到“勾选完成”这条链路要顺畅。这四条铁律帮我省了大量跟AI来回掰扯的时间。因为后面每一次让AI修改功能我都会拿这四条来卡一下这个新功能符不符合“本地优先”如果不符合砍掉这个改动会不会破坏自然语言入口会破坏重新想。2. 开工前的三件套需求拆解、工具选型与提示词策略2.1 把“我想要一个工具”变成可执行的用户故事很多Vibe-coding新手上来就开个对话框说“给我做一个待办清单”然后AI噼里啪啦给你生成一个标准的CRUD页面。这样做出来的东西并没有错但它是“AI的待办清单”不是你的。我习惯先拿5分钟写用户故事。注意不是写软件工程规范里的那种用户故事而是像记日记一样写几个场景早上我打开电脑直接说“上午整理周报素材下午开项目会对齐需求”系统自动生成两条任务分别标上时间。我临时接到活说“周五之前把调研报告初稿交出来重要”系统能识别出deadline和优先级。某个任务不需要了我在卡片上点击删除不能有繁琐的二次确认。这些场景决定了核心数据结构标题、备注、截止时间、优先级、标签、创建时间、完成状态。也决定了界面只需要三块一个输入框、一个任务列表、一个筛选栏。其他所谓的“统计报表”“番茄钟联动”“日历拖拽”统统不在这次范围里。这段剖析后来被我写进项目文档标题就是“我们为什么没有做日历视图”——因为用户故事里没人真的需要它做出来只会让上线时间翻倍。2.2 工具链组合AI编码助手本地服务版本管理我的工具链特别普通但每一件都有明确目的AI编码助手我常用的是一个支持自定义指令的AI编程插件它可以直接在我的代码编辑器里读选中代码、改文件也能在对话框里接受自然语言指令。我没用那种“一键生成整个项目”的花哨工具因为一旦它生成一个巨型工程后头改起来会非常痛苦。浏览器本地存储使用的IndexedDB把任务数据落到本地页面关了再开数据还在。选IndexedDB而不是localStorage就是因为任务数量一多查询和排序方便得多而且还能存比较简单的关系结构。Git管理每完成一个功能就提交一次哪怕只有我一个人在开发。AI改坏了某个文件我可以直接回滚这对于Vibe-coding尤其重要因为没有undo功能的时候AI能帮你写代码也能帮你毁掉代码。这套组合的逻辑很简单AI负责写代码我负责做决策。本地存储保证数据主权Git保证有人替我的糊涂买单。2.3 提示词策略怎么给AI下需求才不会跑偏Vibe-coding最核心的功夫不在代码在“下需求”。我自己总结了一个三段式提示词的模板后面全程都在用你要完成的任务把用户输入的一句话解析成待办任务对象。 输入示例“下周三下午三点提醒我给设计稿回邮件重要” 输出要求只输出JSON不要解释格式为{title:给设计稿回邮件,due_time:2025-XX-XX 15:00,priority:high,tags:[工作]} 边界情况如果没有提到时间due_time填null如果没有提到优先级priority填normal。你只能输出JSON对象不能输出Markdown代码块。看到了吗我把“不要解释”和“只能输出JSON”写死在提示词里。因为AI默认会很热情给你输出一大段“好的我来解析这句话首先我识别到了……”这种废话直接污染程序逻辑。用了这个模板后我拿了几十条真实句子去测试解析成功率从原来的八成不到升到了九成五以上。还必须在提示词里给AI一个“兜底”的出口如果它实在听不懂就输出一个预设的错误标记。比如{error:parse_failed}前端拿到这个标记后弹一个“没听懂换个说法试试”比让程序硬撑着继续跑要体面得多。3. 从零到交付Task5产出的完整实操过程3.1 第一阶段用自然语言搭建界面骨架我不擅长从空白页开始写CSS所以这个阶段我对AI工具的依赖度最高。第一次指令是这样的“帮我做一个待办应用的主界面风格是清爽一点左上方一个大输入框下面用卡片形式展示任务每个卡片要有标题、截止时间、标签右侧有删除按钮。背景用浅灰色字体用系统默认。只写HTML和CSS不要加逻辑。”AI返回了一个还不错的静态页面但第一版问题很多输入框有点小卡片间距不均匀标签颜色是辣眼睛的荧光绿。我继续提修改“输入框高度调成60像素占满页面宽度的80%卡片改成圆角12像素阴影轻一点标签用淡色底、深色字不要用高饱和颜色。”来回改了三轮界面基本顺眼。这里有个经验千万不要让AI一次生成完整的高保真UI。你一句“做得好看一点”它只会生成千篇一律的模板。正确做法是先要一个中规中矩的骨架然后一次只提一个维度的修改比如颜色、间距、字体这样每一轮的输出都可预期。3.2 第二阶段实现自然语言解析核心逻辑界面是壳核心是解析。我在项目里单独建了一个parser.js里面只放一个函数把用户输入交给大模型拿回结构化JSON。实际的请求流程是这样的async function parseTaskInput(rawText) { const response await fetch(/api/parse, { method: POST, headers: { Content-Type: application/json }, body: JSON.stringify({ text: rawText, instruction: 你是任务解析器把用户输入转换成任务对象严格输出JSON }) }); const data await response.json(); if (data.error) return { error: data.error }; // 后端会做一层校验确保priority只能是high/normal/low const task { title: data.title || 未命名任务, due_time: normalizeTime(data.due_time), priority: normalizePriority(data.priority), tags: Array.isArray(data.tags) ? data.tags : [] }; return task; }这里有个容易被忽略的点大模型返回的JSON虽然规范但偶尔也会把due_time写成“2025年2月14日16点”甚至“下午三点”所以我额外写了一个normalizeTime函数来做时间格式的二次归一化。实践下来这一步非常有用它把AI“人性化的表达”和前端“机械化的存储”之间的缝给补上了。我还加了两个防御性检查如果title字段长度超过80个字符说明AI把一个长句整个当成标题了我会截断并提示用户拆分成短句如果tags数组里混入了逗号分隔的长字符串就把它按逗号拆开。这些小逻辑全部是后来测试时被真实场景逼出来的AI不会主动帮你想到。3.3 第三阶段数据持久化与异常兜底数据存储我选用了浏览器自带的IndexedDB。一开始用localStorage更简单但当我测试到第200条任务时明显感觉到读取速度变慢而且没法做“按截止时间排序”这种查询。换到IndexedDB之后查询效率高了不少即使本地存了上千条任务列表滚动也依然流畅。核心的存取封装类似这样import { openDB } from idb; const dbPromise openDB(task-db, 1, { upgrade(db) { if (!db.objectStoreNames.contains(tasks)) { db.createObjectStore(tasks, { keyPath: id, autoIncrement: true }); } } }); async function addTask(task) { const db await dbPromise; return db.add(tasks, { ...task, created_at: new Date().toISOString(), completed: false }); }IndexedDB的API比较啰嗦我就让AI帮我包了一层简化函数。你看这又是Vibe-coding的好搭子你不需要自己记全套IndexedDB方法你只需要告诉AI“我要增删改查帮我封装”它就能给你一个足够好用的版本。数据持久化的另一层是状态恢复。用户刷新页面后列表要能从IndexedDB里读出来并按“未完成优先、截止时间早的在前”排序。这个排序逻辑是一句普通话就能让AI写好的“请按照未完成在前已完成在后同为未完成时按截止时间从早到晚截止时间为空的排在最前面。”AI写了大概二十行的排序函数中间有个日期比较的bug我在测试时发现“空时间”被排到了最前面纠正后就好了。这类小问题在传统开发里需要细查但对着AI说“排序还是不对空时间应该排最后”它改完你就测试效率高不少。3.4 第四阶段联调、测试与打包上线Task5要求“项目产出”所以不能只在编辑器里跑我把它打包成了一个PWA渐进式Web应用。没有做原生移动端是因为PWA一套代码能同时覆盖桌面浏览器和手机浏览器对个人项目来说性价比很高。打包过程中最有价值的测试是“人话测试”。我收集了十几种常见说法包括口语化的“买菜”“明天早上交报告”“提醒我周五联系客户”“把洗衣服这件事做了”等然后分别跑了一遍解析看结果对不对。结果发现“买菜”这种没有任何时间的输入AI会默认补一个“今天”的截止日期这并不符合我的预期——我的设计是无时间就按无时间处理放到一个“待安排”的列表里。于是我把这个规则又写进了系统提示词“如果没有明确时间不要猜时间直接让due_time为null。”改了之后无时间任务才真正归位。最后我用PWA的离线缓存功能让这个应用哪怕断网也能正常打开只是解析需要联网因为要走大模型API。对于本地优先的项目这个折中方案是合理的任务管理数据永远在本地但AI解析这种实时智能行为允许依赖网络。我在项目README里专门写清楚了这一点避免用户产生“明明数据都在本地为什么还要网络”的疑问。4. 复盘那些坑Vibe-coding最容易翻车的四个瞬间4.1 上下文一长AI就“失忆”这是所有Vibe-coding玩家迟早会遇到的问题。当我开始让AI修改第11轮的时候新的回复里明显把之前的代码结构给忘了——它给我插入了一个重复的初始化函数导致页面报错“db is undefined”。我后来养成了一个习惯每完成一个微小功能立刻让AI“总结你刚才生成的代码里哪些函数是核心函数它们的关系是什么”并把这个总结整理成项目备注。下次让AI修改时我把这段备注粘贴给AI作为“项目背景”它就不会胡乱猜了。相当于给AI搭了一个记忆脚手架非常管用。4.2 过度信任AI生成的代码忽略边界在写自然语言解析时我以为后端只需要把大模型返回JSON透传前端就行结果AI生成的代码里没有对priority做枚举校验。实际测试时大模型返回过一个priority:urgent前端渲染直接将“urgent”作为类名加进CSS整个卡片颜色都乱了。后来我在所有AI生成的“前端界面-后端接口”边界处都加了防御性校验逻辑。这个名字听起来很程序化但用大白话说就是不要让AI的“随心所欲”直接流到用户界面上所有来自AI的数据都要在接口处“洗澡消毒”。4.3 提示词里藏着歧义功能做出来不对我有一条指令是“如果有时间信息就解析没有就设置为null”。结果AI每次都返回due_time:null——注意Python风格字段值里的“null”是字符串而不是真正的空值。这个bug特别隐蔽不仔细看根本发现不了导致前端判断due_time null始终为false所有任务都显示“无时间”标签。排查了很久后来在模拟返回结果里打印类型才发现typeof data.due_time是string而不是object。解决办法是在系统提示词里额外写一句“JSON中不要用双引号包住null直接写null不要写成字符串”同时在代码里做了二次处理如果due_time是字符串null也把它转成真正的null。双保险之后这个问题再没出现过。4.4 别让项目成为“AI代码堆砌的艺术品”项目做完了功能都正常但打开main.js一看2800多行了。里面有好几个函数是AI在不同时间生成的重复实现比如formatDate和formatTime实际上干的是同一件事只是分别各自实现了一遍。这样的代码虽然能跑但后续你要改一个时间格式得同时改两处很容易漏。我在交付前做了一轮“AI重构会话”把整个文件丢给AI告诉它“请你找出重复的函数并合并同时保持功能一致改完后输出修改摘要”。它很有效率地把重复部分收敛起来代码从2800行降到了1900行。但这里有个前提我必须提前用Git打了标签重构后的版本跑一遍所有测试用例确定没问题才提交。Vibe-coding不是放任代码不管而是把AI当作“快速起草者”最终的代码质量和可维护性还是得由人来把控。5. 收官之后这套方法论还能怎么用5.1 我复盘出的三条Vibe-coding心法第一永远让AI做“执行者”而不是“架构师”。项目刚开始时我让AI“设计一个待办工具的架构”结果它给了一套复杂的微服务架构方案完全脱离实际。后来改成我自己画一张简单的数据流图再让AI根据这张图去写代码事情一下子就顺了。所谓“Vibe-coding”不是把自己的大脑交给AI而是把AI当成一双特别快、特别听话的手。第二用场景测试代替代码审查。我不太逐行审查AI写的代码而是直接跑“用户故事”输入那句话看卡片是否出现点删除看列表是否更新刷新页面看数据是否还在。只要这几种关键场景都通过剩下的细节bug可以交给日志去暴露。这种方式特别适合单人小项目能让你把时间花在刀刃上。第三“对话”也要讲版本管理。我建了一个叫prompts/的文件夹里面保存了每一个关键提示词的第几版。有人可能会觉得多此一举但当你发现“之前某个版本提示词能得出更好的效果后来改了好像变差了”的时候能随时回退对比这个价值超过你想象。5.2 下一步我准备在这个产出上加什么Task5已经交付但“随手计划”这个项目我不会让它烂尾。接下来我打算做的扩展有三个一是增加“自然语言修改任务”比如你说“把明天的会挪到下午四点”系统能自动找到对应任务并更新二是支持导出JSON/CSV方便把日常记录挪到其他工具里三是增加一个本地备份文件让数据不只依赖浏览器存储。这个扩展路径其实已经写在项目文档里等哪天我又有空可能直接通过几轮自然语言对话把它们全部实现。Vibe-coding这趟收官之旅给我的最大改变不是写代码更快了而是我开始把“快速验证一个想法”当成做项目的默认方式。如果你也刚好卡在某个Task的产出阶段别急着让AI帮你堆功能先坐下来把“这个工具到底解决谁的什么问题”想清楚然后让AI跟着你的节奏跑你会看到完全不一样的产出质量。