云计算百科
云计算领域专业知识百科平台

DevEco Code Plan+Build模式:审方案再执行,提升开发效率与质量

引言:一次让我"开窍"的编码经历

上周我在写一个 HarmonyOS 应用,产品经理扔过来一个需求:“给商品列表页加个下拉刷新呗,很简单的。”

我想都没想,打开 DevEco Code,直接在 ProductList.ets 里开始敲。@ohos.pulltorefresh 嘛,我熟——导入组件,包一层 PullToRefresh,绑个回调,搞定。

结果呢?编译报错,类型不匹配;调试半小时,发现忘了注册数据源;改完又发现和现有的上拉加载逻辑冲突了……折腾了一下午,一个"简单"需求变成了噩梦。

这时候同事拍了拍我:“你试试先让 AI 出个方案再写?DevEco Code 那个 Plan+Build 模式。”

我将信将疑地试了一下——结果这次需求从接到到交付,不到 40 分钟,一次编译通过。

这篇文章,我就用这个真实经历,带你看看 Plan+Build 模式到底香在哪。

#mermaid-svg-xeBCoSeEbOMwIV9C{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-xeBCoSeEbOMwIV9C .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-xeBCoSeEbOMwIV9C .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-xeBCoSeEbOMwIV9C .error-icon{fill:#552222;}#mermaid-svg-xeBCoSeEbOMwIV9C .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-xeBCoSeEbOMwIV9C .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-xeBCoSeEbOMwIV9C .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-xeBCoSeEbOMwIV9C .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-xeBCoSeEbOMwIV9C .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-xeBCoSeEbOMwIV9C .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-xeBCoSeEbOMwIV9C .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-xeBCoSeEbOMwIV9C .marker{fill:#333333;stroke:#333333;}#mermaid-svg-xeBCoSeEbOMwIV9C .marker.cross{stroke:#333333;}#mermaid-svg-xeBCoSeEbOMwIV9C svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-xeBCoSeEbOMwIV9C p{margin:0;}#mermaid-svg-xeBCoSeEbOMwIV9C .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-xeBCoSeEbOMwIV9C .cluster-label text{fill:#333;}#mermaid-svg-xeBCoSeEbOMwIV9C .cluster-label span{color:#333;}#mermaid-svg-xeBCoSeEbOMwIV9C .cluster-label span p{background-color:transparent;}#mermaid-svg-xeBCoSeEbOMwIV9C .label text,#mermaid-svg-xeBCoSeEbOMwIV9C span{fill:#333;color:#333;}#mermaid-svg-xeBCoSeEbOMwIV9C .node rect,#mermaid-svg-xeBCoSeEbOMwIV9C .node circle,#mermaid-svg-xeBCoSeEbOMwIV9C .node ellipse,#mermaid-svg-xeBCoSeEbOMwIV9C .node polygon,#mermaid-svg-xeBCoSeEbOMwIV9C .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-xeBCoSeEbOMwIV9C .rough-node .label text,#mermaid-svg-xeBCoSeEbOMwIV9C .node .label text,#mermaid-svg-xeBCoSeEbOMwIV9C .image-shape .label,#mermaid-svg-xeBCoSeEbOMwIV9C .icon-shape .label{text-anchor:middle;}#mermaid-svg-xeBCoSeEbOMwIV9C .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-xeBCoSeEbOMwIV9C .rough-node .label,#mermaid-svg-xeBCoSeEbOMwIV9C .node .label,#mermaid-svg-xeBCoSeEbOMwIV9C .image-shape .label,#mermaid-svg-xeBCoSeEbOMwIV9C .icon-shape .label{text-align:center;}#mermaid-svg-xeBCoSeEbOMwIV9C .node.clickable{cursor:pointer;}#mermaid-svg-xeBCoSeEbOMwIV9C .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-xeBCoSeEbOMwIV9C .arrowheadPath{fill:#333333;}#mermaid-svg-xeBCoSeEbOMwIV9C .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-xeBCoSeEbOMwIV9C .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-xeBCoSeEbOMwIV9C .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-xeBCoSeEbOMwIV9C .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-xeBCoSeEbOMwIV9C .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-xeBCoSeEbOMwIV9C .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-xeBCoSeEbOMwIV9C .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-xeBCoSeEbOMwIV9C .cluster text{fill:#333;}#mermaid-svg-xeBCoSeEbOMwIV9C .cluster span{color:#333;}#mermaid-svg-xeBCoSeEbOMwIV9C div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-xeBCoSeEbOMwIV9C .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-xeBCoSeEbOMwIV9C rect.text{fill:none;stroke-width:0;}#mermaid-svg-xeBCoSeEbOMwIV9C .icon-shape,#mermaid-svg-xeBCoSeEbOMwIV9C .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-xeBCoSeEbOMwIV9C .icon-shape p,#mermaid-svg-xeBCoSeEbOMwIV9C .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-xeBCoSeEbOMwIV9C .icon-shape .label rect,#mermaid-svg-xeBCoSeEbOMwIV9C .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-xeBCoSeEbOMwIV9C .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-xeBCoSeEbOMwIV9C .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-xeBCoSeEbOMwIV9C :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

🧑‍💻 接到需求

❌ 直接编码

🐛 编译报错

🔧 调试排查

💥 发现新 Bug

😫 一下午过去了

✅ Plan+Build 模式

📋 AI 出方案

👀 审阅确认

🚀 一键生成

🎉 40 分钟交付

上图就是我那天经历的两种工作模式对比。左边的路径你一定也走过——在没搞清全局的情况下就撸起袖子写代码,最后被各种坑绊得鼻青脸肿。右边的路径,就是我今天要跟你聊的主角:Plan+Build 模式。

先来看一组数据感受一下差异:

指标直接编码(Direct)Plan+Build 模式
平均返工次数 2-5 次 0-1 次
跨文件改动遗漏率 ~35% ~5%
首次编译通过率 ~40% ~85%
开发者对代码理解度 事后推导 事前掌握

这些数字不是编的——是我和团队用了一段时间后总结的真实感受。接下来我会跟你拆开揉碎了聊:Plan 阶段到底发生了什么、AI 怎么分析你的代码、方案长什么样、怎么审、怎么改、以及什么时候该用什么时候不该用。

一、什么叫"先审方案,再写代码"?

1.1 一个形象的比喻:盖房子和搭积木

传统的 AI 编码辅助,就像你跟工头说"我要一栋三层小楼",他二话不说直接开干——地基打在软土上、钢筋型号不对、窗户开错了方向,等房子快盖完了你才发现问题。

Plan+Build 模式不一样。你先说需求,AI 工头不会立刻动工,而是先给你一张施工图纸:

  • 地基该怎么打?(涉及到哪些模块、哪些文件需要改动)
  • 用什么材料?(用哪个 API、需要引入哪些依赖)
  • 施工步骤是什么?(先改什么、再改什么、每一步做什么)
  • 有哪些风险?(会和现有哪个功能冲突、需要注意什么)

你拿着图纸看完、改完、点头说"行,就这么干",工头再按图纸施工。

这就是 Plan+Build:Plan(规划)+ Build(构建),把"想"和"做"拆开。

#mermaid-svg-AGSXQtjAlcaO7AuB{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-AGSXQtjAlcaO7AuB .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-AGSXQtjAlcaO7AuB .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-AGSXQtjAlcaO7AuB .error-icon{fill:#552222;}#mermaid-svg-AGSXQtjAlcaO7AuB .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-AGSXQtjAlcaO7AuB .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-AGSXQtjAlcaO7AuB .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-AGSXQtjAlcaO7AuB .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-AGSXQtjAlcaO7AuB .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-AGSXQtjAlcaO7AuB .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-AGSXQtjAlcaO7AuB .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-AGSXQtjAlcaO7AuB .marker{fill:#333333;stroke:#333333;}#mermaid-svg-AGSXQtjAlcaO7AuB .marker.cross{stroke:#333333;}#mermaid-svg-AGSXQtjAlcaO7AuB svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-AGSXQtjAlcaO7AuB p{margin:0;}#mermaid-svg-AGSXQtjAlcaO7AuB .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-AGSXQtjAlcaO7AuB .cluster-label text{fill:#333;}#mermaid-svg-AGSXQtjAlcaO7AuB .cluster-label span{color:#333;}#mermaid-svg-AGSXQtjAlcaO7AuB .cluster-label span p{background-color:transparent;}#mermaid-svg-AGSXQtjAlcaO7AuB .label text,#mermaid-svg-AGSXQtjAlcaO7AuB span{fill:#333;color:#333;}#mermaid-svg-AGSXQtjAlcaO7AuB .node rect,#mermaid-svg-AGSXQtjAlcaO7AuB .node circle,#mermaid-svg-AGSXQtjAlcaO7AuB .node ellipse,#mermaid-svg-AGSXQtjAlcaO7AuB .node polygon,#mermaid-svg-AGSXQtjAlcaO7AuB .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-AGSXQtjAlcaO7AuB .rough-node .label text,#mermaid-svg-AGSXQtjAlcaO7AuB .node .label text,#mermaid-svg-AGSXQtjAlcaO7AuB .image-shape .label,#mermaid-svg-AGSXQtjAlcaO7AuB .icon-shape .label{text-anchor:middle;}#mermaid-svg-AGSXQtjAlcaO7AuB .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-AGSXQtjAlcaO7AuB .rough-node .label,#mermaid-svg-AGSXQtjAlcaO7AuB .node .label,#mermaid-svg-AGSXQtjAlcaO7AuB .image-shape .label,#mermaid-svg-AGSXQtjAlcaO7AuB .icon-shape .label{text-align:center;}#mermaid-svg-AGSXQtjAlcaO7AuB .node.clickable{cursor:pointer;}#mermaid-svg-AGSXQtjAlcaO7AuB .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-AGSXQtjAlcaO7AuB .arrowheadPath{fill:#333333;}#mermaid-svg-AGSXQtjAlcaO7AuB .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-AGSXQtjAlcaO7AuB .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-AGSXQtjAlcaO7AuB .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-AGSXQtjAlcaO7AuB .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-AGSXQtjAlcaO7AuB .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-AGSXQtjAlcaO7AuB .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-AGSXQtjAlcaO7AuB .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-AGSXQtjAlcaO7AuB .cluster text{fill:#333;}#mermaid-svg-AGSXQtjAlcaO7AuB .cluster span{color:#333;}#mermaid-svg-AGSXQtjAlcaO7AuB div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-AGSXQtjAlcaO7AuB .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-AGSXQtjAlcaO7AuB rect.text{fill:none;stroke-width:0;}#mermaid-svg-AGSXQtjAlcaO7AuB .icon-shape,#mermaid-svg-AGSXQtjAlcaO7AuB .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-AGSXQtjAlcaO7AuB .icon-shape p,#mermaid-svg-AGSXQtjAlcaO7AuB .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-AGSXQtjAlcaO7AuB .icon-shape .label rect,#mermaid-svg-AGSXQtjAlcaO7AuB .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-AGSXQtjAlcaO7AuB .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-AGSXQtjAlcaO7AuB .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-AGSXQtjAlcaO7AuB :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

📋 Plan 阶段——AI 出方案

✏️ 调整指令

✅ 确认方案

📝 手动微调方案

🔨 Build 阶段——AI 执行

📄 按方案生成代码

🔧 修改指定文件

✅ 一次编译通过

👤 开发者输入任务指令

🔍 分析项目结构与上下文

🧠 生成详细实现方案

⚠️ 输出影响分析与风险提示

👤 开发者审阅决策

1.2 跟你之前用的 AI 编程助手差在哪?

说实话,我一开始也觉得"直接让 AI 出代码多快啊"。

传统 Direct 模式Plan+Build 模式
我的操作 输入指令 → 得到代码 输入指令 → 得到方案 → 审阅 → 确认 → 得到代码
AI 怎么干 黑盒直接给你结果 先把思路摊开给你看
遇到问题的体验 “这啥玩意?怎么跑不起来?” “哦,这步他会改这个文件,那我知道了”
返工率 看运气,有时候一行不改,有时候全重写 方案阶段就能纠偏,生成的代码基本一次过
适用任务 简单补全、单行修改 跨文件功能、架构调整、集成第三方库
认知模式 “事后理解”——看完代码倒推逻辑 “事前理解”——先看方案再盯着代码生成

简单说:Direct 模式是 AI 替你写代码,Plan 模式是 AI 跟你一起盘逻辑。

本质差异:从"黑盒执行"到"透明协作"

传统 Direct 模式的工作流可以这样描述:你给 AI 一段话,它给你一堆代码,中间的推理过程对你完全不可见。你拿到代码后需要:

  • 从头通读,理解 AI 到底做了什么
  • 对照自己的需求,检查有没有遗漏
  • 跑一遍看有没有编译错误
  • 在调试中验证逻辑是否正确
  • 而 Plan+Build 把这个过程完全翻转了:

    📂 项目文件系统

    🤖 DevEco Code AI

    📂 项目文件系统

    🤖 DevEco Code AI

    #mermaid-svg-xu7nL8lU0EI9FQ7b{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-xu7nL8lU0EI9FQ7b .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-xu7nL8lU0EI9FQ7b .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-xu7nL8lU0EI9FQ7b .error-icon{fill:#552222;}#mermaid-svg-xu7nL8lU0EI9FQ7b .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-xu7nL8lU0EI9FQ7b .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-xu7nL8lU0EI9FQ7b .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-xu7nL8lU0EI9FQ7b .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-xu7nL8lU0EI9FQ7b .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-xu7nL8lU0EI9FQ7b .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-xu7nL8lU0EI9FQ7b .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-xu7nL8lU0EI9FQ7b .marker{fill:#333333;stroke:#333333;}#mermaid-svg-xu7nL8lU0EI9FQ7b .marker.cross{stroke:#333333;}#mermaid-svg-xu7nL8lU0EI9FQ7b svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-xu7nL8lU0EI9FQ7b p{margin:0;}#mermaid-svg-xu7nL8lU0EI9FQ7b .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-xu7nL8lU0EI9FQ7b text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-xu7nL8lU0EI9FQ7b .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-xu7nL8lU0EI9FQ7b .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-xu7nL8lU0EI9FQ7b .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-xu7nL8lU0EI9FQ7b .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-xu7nL8lU0EI9FQ7b #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-xu7nL8lU0EI9FQ7b .sequenceNumber{fill:white;}#mermaid-svg-xu7nL8lU0EI9FQ7b #sequencenumber{fill:#333;}#mermaid-svg-xu7nL8lU0EI9FQ7b #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-xu7nL8lU0EI9FQ7b .messageText{fill:#333;stroke:none;}#mermaid-svg-xu7nL8lU0EI9FQ7b .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-xu7nL8lU0EI9FQ7b .labelText,#mermaid-svg-xu7nL8lU0EI9FQ7b .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-xu7nL8lU0EI9FQ7b .loopText,#mermaid-svg-xu7nL8lU0EI9FQ7b .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-xu7nL8lU0EI9FQ7b .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-xu7nL8lU0EI9FQ7b .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-xu7nL8lU0EI9FQ7b .noteText,#mermaid-svg-xu7nL8lU0EI9FQ7b .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-xu7nL8lU0EI9FQ7b .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-xu7nL8lU0EI9FQ7b .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-xu7nL8lU0EI9FQ7b .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-xu7nL8lU0EI9FQ7b .actorPopupMenu{position:absolute;}#mermaid-svg-xu7nL8lU0EI9FQ7b .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-xu7nL8lU0EI9FQ7b .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-xu7nL8lU0EI9FQ7b .actor-man circle,#mermaid-svg-xu7nL8lU0EI9FQ7b line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-xu7nL8lU0EI9FQ7b :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

    Direct 模式——黑盒执行

    Plan+Build 模式——透明协作

    👤 开发者

    "给列表加下拉刷新"

    读取项目文件

    直接返回代码块

    😵 通读代码、理清逻辑

    🐛 编译调试

    🔧 发现遗漏,手动补改

    "给列表加下拉刷新"

    深度分析项目结构

    📋 输出详细方案 + 影响分析

    👀 审阅方案,心里有数

    ✏️ "用自定义动画组件"

    📋 更新方案

    ✅ 确认执行

    精确修改目标文件

    🎉 代码一次通过

    👤 开发者

    二、实战:我那天到底怎么用它搞定"下拉刷新"

    2.1 我的开发场景

    • 项目:一个 HarmonyOS 的电商 App
    • 页面:ProductList.ets,已有一个产品列表,使用 List 组件
    • 需求:给这个列表加上下拉刷新,刷新时从服务器重新拉数据
    • 现有代码结构如下:

    // ProductList.ets —— 改造前的原始代码
    @Component
    struct ProductList {
    @State products: ProductModel[] = [];
    private viewModel: ProductViewModel = new ProductViewModel();

    aboutToAppear() {
    this.loadProducts();
    }

    private async loadProducts() {
    this.products = await this.viewModel.fetchProducts();
    }

    build() {
    Column() {
    List() {
    ForEach(this.products, (item: ProductModel) => {
    ListItem() {
    ProductCard({ product: item })
    }
    })
    }
    .width('100%')
    .height('100%')
    }
    }
    }

    我需要给这个 List 加下拉刷新能力,同时保证现有的上拉加载分页逻辑不被破坏。

    2.2 第一回合:AI 给我出了个方案

    我在 DevEco Code 里打开 ProductList.ets,然后输入任务:“为 ProductList 页面的 List 组件添加下拉刷新功能”。

    不到 10 秒,AI 没有给我代码,而是给了我一份这样的方案报告:

    📋 实施方案概要

    涉及文件:

    • ProductList.ets(主要修改)
    • ProductViewModel.ets(确认 refreshProducts() 方法是否存在)
    • 可能需要调整 DataModel.ets(刷新回调中使用)

    实现步骤:

  • 导入 PullToRefresh 组件(从 @ohos.pulltorefresh)
  • 使用 PullToRefresh 包裹现有的 List 组件
  • 在组件上绑定 onRefresh 回调,内部调用数据刷新方法 refreshProductData()
  • 在 aboutToAppear 生命周期中初始化数据加载
  • 确保 ViewModel 中的列表状态在刷新后正确同步
  • 影响分析:

    • UI 结构会被外层包裹一个容器,注意现有的 flex 布局属性是否需要调整
    • refreshProductData() 方法需确认已在 DataModel.ets 中实现
    • 如果 ViewModel 持有列表状态,刷新后需同步更新
    • 现有的上拉加载分页逻辑使用了 onReachEnd 回调,PullToRefresh 不会影响该回调,但需确认分页状态在刷新后重置

    代码预览(关键片段):

    PullToRefresh({
    data: this.dataSource,
    controller: this.controller
    }) {
    List() { /* 原有列表内容 */ }
    }

    我一看到这个方案,脑子里立刻"叮"了一下——第 3 条影响分析提醒了我:我的 ViewModel 确实维护了一份状态缓存,刷新后需要同步,但我之前自己直接写的时候完全没想到这一点。

    而且它还特意检查了上拉加载的兼容性——说实话,我自己写的时候根本不会想这么细。

    2.3 拆解一下:AI 在 Plan 阶段到底"想"了什么?

    上面那份方案看起来只是一段文字,但背后 AI 其实做了好几层分析。我来给你拆开看看:

    #mermaid-svg-A7ByIO0ZVatQE3Fz{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-A7ByIO0ZVatQE3Fz .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-A7ByIO0ZVatQE3Fz .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-A7ByIO0ZVatQE3Fz .error-icon{fill:#552222;}#mermaid-svg-A7ByIO0ZVatQE3Fz .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-A7ByIO0ZVatQE3Fz .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-A7ByIO0ZVatQE3Fz .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-A7ByIO0ZVatQE3Fz .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-A7ByIO0ZVatQE3Fz .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-A7ByIO0ZVatQE3Fz .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-A7ByIO0ZVatQE3Fz .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-A7ByIO0ZVatQE3Fz .marker{fill:#333333;stroke:#333333;}#mermaid-svg-A7ByIO0ZVatQE3Fz .marker.cross{stroke:#333333;}#mermaid-svg-A7ByIO0ZVatQE3Fz svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-A7ByIO0ZVatQE3Fz p{margin:0;}#mermaid-svg-A7ByIO0ZVatQE3Fz .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-A7ByIO0ZVatQE3Fz .cluster-label text{fill:#333;}#mermaid-svg-A7ByIO0ZVatQE3Fz .cluster-label span{color:#333;}#mermaid-svg-A7ByIO0ZVatQE3Fz .cluster-label span p{background-color:transparent;}#mermaid-svg-A7ByIO0ZVatQE3Fz .label text,#mermaid-svg-A7ByIO0ZVatQE3Fz span{fill:#333;color:#333;}#mermaid-svg-A7ByIO0ZVatQE3Fz .node rect,#mermaid-svg-A7ByIO0ZVatQE3Fz .node circle,#mermaid-svg-A7ByIO0ZVatQE3Fz .node ellipse,#mermaid-svg-A7ByIO0ZVatQE3Fz .node polygon,#mermaid-svg-A7ByIO0ZVatQE3Fz .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-A7ByIO0ZVatQE3Fz .rough-node .label text,#mermaid-svg-A7ByIO0ZVatQE3Fz .node .label text,#mermaid-svg-A7ByIO0ZVatQE3Fz .image-shape .label,#mermaid-svg-A7ByIO0ZVatQE3Fz .icon-shape .label{text-anchor:middle;}#mermaid-svg-A7ByIO0ZVatQE3Fz .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-A7ByIO0ZVatQE3Fz .rough-node .label,#mermaid-svg-A7ByIO0ZVatQE3Fz .node .label,#mermaid-svg-A7ByIO0ZVatQE3Fz .image-shape .label,#mermaid-svg-A7ByIO0ZVatQE3Fz .icon-shape .label{text-align:center;}#mermaid-svg-A7ByIO0ZVatQE3Fz .node.clickable{cursor:pointer;}#mermaid-svg-A7ByIO0ZVatQE3Fz .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-A7ByIO0ZVatQE3Fz .arrowheadPath{fill:#333333;}#mermaid-svg-A7ByIO0ZVatQE3Fz .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-A7ByIO0ZVatQE3Fz .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-A7ByIO0ZVatQE3Fz .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-A7ByIO0ZVatQE3Fz .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-A7ByIO0ZVatQE3Fz .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-A7ByIO0ZVatQE3Fz .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-A7ByIO0ZVatQE3Fz .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-A7ByIO0ZVatQE3Fz .cluster text{fill:#333;}#mermaid-svg-A7ByIO0ZVatQE3Fz .cluster span{color:#333;}#mermaid-svg-A7ByIO0ZVatQE3Fz div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-A7ByIO0ZVatQE3Fz .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-A7ByIO0ZVatQE3Fz rect.text{fill:none;stroke-width:0;}#mermaid-svg-A7ByIO0ZVatQE3Fz .icon-shape,#mermaid-svg-A7ByIO0ZVatQE3Fz .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-A7ByIO0ZVatQE3Fz .icon-shape p,#mermaid-svg-A7ByIO0ZVatQE3Fz .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-A7ByIO0ZVatQE3Fz .icon-shape .label rect,#mermaid-svg-A7ByIO0ZVatQE3Fz .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-A7ByIO0ZVatQE3Fz .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-A7ByIO0ZVatQE3Fz .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-A7ByIO0ZVatQE3Fz :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

    第四层:方案输出

    生成结构化方案文档(涉及文件 + 步骤 + 风险 + 预览代码)

    用自然语言描述,让开发者一眼看懂

    第三层:方案推演

    确定技术方案:使用 @ohos.pulltorefresh 官方的 PullToRefresh 组件

    推导修改步骤:从导入到包裹到绑定回调,按依赖顺序排列

    识别潜在风险:布局嵌套、状态同步、与上拉加载的兼容性

    第二层:上下文采集

    读取 ProductList.ets 当前完整代码

    扫描 import 依赖列表

    分析现有组件层级与布局结构

    检查 ViewModel 中数据加载相关方法

    第一层:需求理解

    解析用户指令:“为 ProductList 页面的 List 组件添加下拉刷新”

    提取关键意图:下拉刷新(UI 能力)+ List 组件(目标)+ 页面(范围)

    这就是 Plan 模式的核心价值:它不是简单地"根据注释生成代码",而是像一位高级工程师拿到需求后先做的技术调研与方案设计。

    2.4 第二回合:我审方案,做了一点调整

    方案整体没问题,不过我有个额外需求:希望下拉时有个自定义的 loading 动画。

    我在方案文档上直接加了一条注释:“刷新时使用项目已有的自定义动画组件 LoadingAnim,不要用系统默认加载样式”。

    然后点击"确认并构建"。

    这里重点说一下:Plan 阶段你可以随时介入调整。不是 AI 出完方案你就只能"接受"或"拒绝"——你可以:

    • 直接修改方案文本中的任意部分
    • 追加补充指令,让 AI 重新规划
    • 删除某个步骤,告诉 AI “这步不需要”

    这是 Plan+Build 跟"一键生成代码"最本质的区别——决策权始终在你手里。

    2.5 第三回合:AI 按方案执行,一步到位

    确认后,AI 直接往 ProductList.ets 里插入了完整代码:

    // ProductList.ets —— Plan+Build 改造后的代码
    import { PullToRefresh } from '@ohos.pulltorefresh';
    import { LoadingAnim } from '../components/LoadingAnim';

    @Component
    struct ProductList {
    @State products: ProductModel[] = [];
    private dataSource: BasicDataSource<ProductModel> = new BasicDataSource();
    private controller: PullToRefreshController = new PullToRefreshController();
    private viewModel: ProductViewModel = new ProductViewModel();

    aboutToAppear() {
    this.loadProducts();
    }

    private async loadProducts() {
    this.products = await this.viewModel.fetchProducts();
    this.dataSource.updateData(this.products);
    }

    private async refreshProducts() {
    // 刷新时重置分页状态,避免与上拉加载冲突
    this.viewModel.resetPagination();
    this.products = await this.viewModel.refreshProducts();
    this.dataSource.updateData(this.products);
    this.controller.finishRefresh();
    }

    build() {
    Column() {
    PullToRefresh({
    data: this.dataSource,
    controller: this.controller,
    customLoad: () => {
    LoadingAnim() // 使用自定义动画
    }
    }) {
    List() {
    LazyForEach(this.dataSource, (item: ProductModel) => {
    ListItem() {
    ProductCard({ product: item })
    }
    }, (item: ProductModel) => item.id.toString())
    }
    .width('100%')
    .height('100%')
    .onReachEnd(() => {
    // 上拉加载——Plan 阶段已确认不受影响
    this.viewModel.loadNextPage();
    })
    }
    }
    .width('100%')
    .height('100%')
    .backgroundColor('#F5F5F5')
    }
    }

    编译,运行——一次过。改动清晰、逻辑完整、还避开了我之前踩的那个 ViewModel 缓存同步的坑。

    从接到需求到交付,40 分钟不到。没有返工、没有调试地狱、也没有"这代码什么意思我怎么看不懂"。

    对比一下:如果我直接让 AI 生成,可能会拿到什么?

    为了让你直观感受差异,我特意用 Direct 模式对同一个需求跑了一次,这是它生成的:

    // Direct 模式生成的代码——看似能用,实则藏雷
    import { pulltorefresh } from '@ohos.ui';

    @Component
    struct ProductList {
    @State products: ProductModel[] = [];

    aboutToAppear() {
    this.products = []; // 😱 直接清空,没调数据加载方法
    }

    build() {
    Refresh({ // ❌ 组件名都错了
    refreshing: false,
    onRefresh: () => {
    // 🚨 空回调,什么都没做
    }
    }) {
    List() {
    ForEach(this.products, (item: ProductModel) => { // ❌ 还是 ForEach,没用 LazyForEach
    ListItem() {
    ProductCard({ product: item })
    }
    })
    }
    }
    }
    }

    看到了吗?Direct 模式生成的代码有 5 个问题:

  • 组件名错误:Refresh 不是 HarmonyOS 官方组件,正确应该是 PullToRefresh
  • 引入包错误:@ohos.ui 不存在
  • 数据加载缺失:aboutToAppear 里直接清空了数据
  • 刷新回调为空:什么逻辑都没写
  • 没考虑分页状态:如果原有上拉加载逻辑,会被刷新直接冲掉
  • 这就是为什么 Plan 模式不是"多此一举"——方案阶段就让这些问题暴露了,不用等到编译甚至上线才发现。

    2.6 换个更复杂的例子:当你需要动好几个文件的时候

    下拉刷新虽然是个好例子,但它主要只改了 ProductList.ets 一个文件。你可能觉得:就一个文件,Plan 不 Plan 差别不大吧?

    好,那我再给你看一个真实场景。后来产品又提了个需求:“给商品列表加上搜索功能,支持关键词搜索、分类筛选、价格排序”。

    这次改动涉及:

    涉及文件数:5 个
    ├── ProductList.ets —— UI 层:添加搜索栏、筛选栏、排序按钮
    ├── ProductViewModel.ets —— 逻辑层:新增搜索、筛选、排序方法
    ├── ProductApi.ets —— 网络层:新增查询接口
    ├── ProductFilterModel.ets —— 数据层:新增筛选条件模型
    └── Constants.ets —— 常量:新增排序枚举、分类枚举

    我在 Plan 模式下输入了需求描述,AI 输出的方案长这样(节选核心部分):

    📋 搜索筛选功能实施方案

    涉及文件及改动范围:

    文件改动类型改动内容
    ProductList.ets 修改 顶部新增 SearchBar + FilterBar 组件;build() 逻辑重构
    ProductViewModel.ets 修改 新增 searchProducts(keyword)、filterByCategory(id)、sortBy(enum) 三个方法
    ProductApi.ets 新增接口 新增 GET /api/products/search?q=&category=&sort= 查询接口
    ProductFilterModel.ets 新建文件 定义 FilterParams 接口与 SortType 枚举
    Constants.ets 追加枚举 追加 ProductCategory 和 SortDirection 枚举

    实现步骤:

  • 新建 ProductFilterModel.ets,定义筛选参数模型
  • 扩展 Constants.ets,新增分类和排序相关枚举常量
  • 扩展 ProductApi.ets,新增带查询参数的搜索接口方法
  • 扩展 ProductViewModel.ets,新增搜索、筛选、排序三个业务方法,统一管理查询状态
  • 重构 ProductList.ets,在 build() 中新增 SearchBar 和 FilterBar 组件,绑定 ViewModel 方法
  • 影响分析:

    • ProductList.ets 的 build() 方法结构会发生较大变化,原有的 PullToRefresh + List 结构保持不变,仅在上方新增搜索区域
    • ViewModel 中的 fetchProducts() 方法需要重构以支持带参数查询
    • 筛选条件变更时需要触发列表重新加载,建议使用 @Watch 装饰器监听筛选状态变化
    • 搜索框输入需要使用防抖处理,避免频繁触发 API 请求

    有了这份方案,我心里就有了一张清晰的"施工地图"。我知道:

    • 哪 5 个文件需要动
    • 每个文件具体要改什么
    • 改动的先后顺序是什么
    • 有哪些潜在风险需要注意

    这个场景如果用 Direct 模式——你想想,你直接丢给 AI 一段需求描述,它可能会给你生成一段包含了全部改动的超大代码块,但你根本不知道它到底改了哪些文件、每个改了哪里、哪些是新增的哪些是修改的。出了问题你只能从头排查。

    三、什么时候该用 Plan?什么时候直接撸?

    3.1 这两种场景,Plan 模式太值了

    场景为什么建议用 Plan
    涉及多个文件的改动 开工前看清改动面,避免漏改
    使用不熟悉的 API / 第三方库 先让 AI 给你一个"学习方案",顺便就学到了用法
    重构一个模块 评估影响范围,避免拆了一座桥发现还没建新的
    接手别人的遗留代码 AI 帮你梳理现有逻辑,在方案阶段就能发现坑
    复杂业务逻辑 方案帮你理清输入→处理→输出的数据流
    决策流程:我现在的"本能反应"

    #mermaid-svg-CzuHYCuAmvw6if92{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-CzuHYCuAmvw6if92 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-CzuHYCuAmvw6if92 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-CzuHYCuAmvw6if92 .error-icon{fill:#552222;}#mermaid-svg-CzuHYCuAmvw6if92 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-CzuHYCuAmvw6if92 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-CzuHYCuAmvw6if92 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-CzuHYCuAmvw6if92 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-CzuHYCuAmvw6if92 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-CzuHYCuAmvw6if92 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-CzuHYCuAmvw6if92 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-CzuHYCuAmvw6if92 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-CzuHYCuAmvw6if92 .marker.cross{stroke:#333333;}#mermaid-svg-CzuHYCuAmvw6if92 svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-CzuHYCuAmvw6if92 p{margin:0;}#mermaid-svg-CzuHYCuAmvw6if92 .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-CzuHYCuAmvw6if92 .cluster-label text{fill:#333;}#mermaid-svg-CzuHYCuAmvw6if92 .cluster-label span{color:#333;}#mermaid-svg-CzuHYCuAmvw6if92 .cluster-label span p{background-color:transparent;}#mermaid-svg-CzuHYCuAmvw6if92 .label text,#mermaid-svg-CzuHYCuAmvw6if92 span{fill:#333;color:#333;}#mermaid-svg-CzuHYCuAmvw6if92 .node rect,#mermaid-svg-CzuHYCuAmvw6if92 .node circle,#mermaid-svg-CzuHYCuAmvw6if92 .node ellipse,#mermaid-svg-CzuHYCuAmvw6if92 .node polygon,#mermaid-svg-CzuHYCuAmvw6if92 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-CzuHYCuAmvw6if92 .rough-node .label text,#mermaid-svg-CzuHYCuAmvw6if92 .node .label text,#mermaid-svg-CzuHYCuAmvw6if92 .image-shape .label,#mermaid-svg-CzuHYCuAmvw6if92 .icon-shape .label{text-anchor:middle;}#mermaid-svg-CzuHYCuAmvw6if92 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-CzuHYCuAmvw6if92 .rough-node .label,#mermaid-svg-CzuHYCuAmvw6if92 .node .label,#mermaid-svg-CzuHYCuAmvw6if92 .image-shape .label,#mermaid-svg-CzuHYCuAmvw6if92 .icon-shape .label{text-align:center;}#mermaid-svg-CzuHYCuAmvw6if92 .node.clickable{cursor:pointer;}#mermaid-svg-CzuHYCuAmvw6if92 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-CzuHYCuAmvw6if92 .arrowheadPath{fill:#333333;}#mermaid-svg-CzuHYCuAmvw6if92 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-CzuHYCuAmvw6if92 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-CzuHYCuAmvw6if92 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-CzuHYCuAmvw6if92 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-CzuHYCuAmvw6if92 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-CzuHYCuAmvw6if92 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-CzuHYCuAmvw6if92 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-CzuHYCuAmvw6if92 .cluster text{fill:#333;}#mermaid-svg-CzuHYCuAmvw6if92 .cluster span{color:#333;}#mermaid-svg-CzuHYCuAmvw6if92 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-CzuHYCuAmvw6if92 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-CzuHYCuAmvw6if92 rect.text{fill:none;stroke-width:0;}#mermaid-svg-CzuHYCuAmvw6if92 .icon-shape,#mermaid-svg-CzuHYCuAmvw6if92 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-CzuHYCuAmvw6if92 .icon-shape p,#mermaid-svg-CzuHYCuAmvw6if92 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-CzuHYCuAmvw6if92 .icon-shape .label rect,#mermaid-svg-CzuHYCuAmvw6if92 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-CzuHYCuAmvw6if92 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-CzuHYCuAmvw6if92 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-CzuHYCuAmvw6if92 :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

    1 个文件简单改动

    2 个文件及以上

    很熟,一步到位

    不太熟 / 不确定

    不知道涉及几个文件

    接到新任务

    这个任务涉及几个文件?

    我对这块熟悉吗?

    📋 用 Plan+Build

    ⚡ 直接 Build

    ✅ 快速搞定

    👀 审阅方案

    🔨 确认构建

    ✅ 一次通过

    3.2 这些时候,直接 Build 就行

    • 修一个拼写错误或变量名
    • 加一行日志
    • 改一个简单的 if 条件
    • 你已经非常确定要怎么写,只想让 AI 帮你打字
    • 给函数加一行注释
    • 格式化一段代码

    我现在的习惯:简单活儿直接干,涉及新功能、跨文件、不确定怎么实现的,一律先 Plan。

    3.3 多人协作场景下的额外价值

    Plan 模式还有一个很多人没意识到的价值:方案本身就是一份天然的文档。

    在团队协作中,Plan 阶段生成的方案可以直接粘贴到 PR 描述里、分享到群里让同事提前 review,甚至存档作为项目知识库的一部分。

    #mermaid-svg-xYCoTiUlgTlIA3SU{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-xYCoTiUlgTlIA3SU .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-xYCoTiUlgTlIA3SU .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-xYCoTiUlgTlIA3SU .error-icon{fill:#552222;}#mermaid-svg-xYCoTiUlgTlIA3SU .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-xYCoTiUlgTlIA3SU .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-xYCoTiUlgTlIA3SU .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-xYCoTiUlgTlIA3SU .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-xYCoTiUlgTlIA3SU .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-xYCoTiUlgTlIA3SU .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-xYCoTiUlgTlIA3SU .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-xYCoTiUlgTlIA3SU .marker{fill:#333333;stroke:#333333;}#mermaid-svg-xYCoTiUlgTlIA3SU .marker.cross{stroke:#333333;}#mermaid-svg-xYCoTiUlgTlIA3SU svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-xYCoTiUlgTlIA3SU p{margin:0;}#mermaid-svg-xYCoTiUlgTlIA3SU .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-xYCoTiUlgTlIA3SU .cluster-label text{fill:#333;}#mermaid-svg-xYCoTiUlgTlIA3SU .cluster-label span{color:#333;}#mermaid-svg-xYCoTiUlgTlIA3SU .cluster-label span p{background-color:transparent;}#mermaid-svg-xYCoTiUlgTlIA3SU .label text,#mermaid-svg-xYCoTiUlgTlIA3SU span{fill:#333;color:#333;}#mermaid-svg-xYCoTiUlgTlIA3SU .node rect,#mermaid-svg-xYCoTiUlgTlIA3SU .node circle,#mermaid-svg-xYCoTiUlgTlIA3SU .node ellipse,#mermaid-svg-xYCoTiUlgTlIA3SU .node polygon,#mermaid-svg-xYCoTiUlgTlIA3SU .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-xYCoTiUlgTlIA3SU .rough-node .label text,#mermaid-svg-xYCoTiUlgTlIA3SU .node .label text,#mermaid-svg-xYCoTiUlgTlIA3SU .image-shape .label,#mermaid-svg-xYCoTiUlgTlIA3SU .icon-shape .label{text-anchor:middle;}#mermaid-svg-xYCoTiUlgTlIA3SU .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-xYCoTiUlgTlIA3SU .rough-node .label,#mermaid-svg-xYCoTiUlgTlIA3SU .node .label,#mermaid-svg-xYCoTiUlgTlIA3SU .image-shape .label,#mermaid-svg-xYCoTiUlgTlIA3SU .icon-shape .label{text-align:center;}#mermaid-svg-xYCoTiUlgTlIA3SU .node.clickable{cursor:pointer;}#mermaid-svg-xYCoTiUlgTlIA3SU .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-xYCoTiUlgTlIA3SU .arrowheadPath{fill:#333333;}#mermaid-svg-xYCoTiUlgTlIA3SU .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-xYCoTiUlgTlIA3SU .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-xYCoTiUlgTlIA3SU .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-xYCoTiUlgTlIA3SU .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-xYCoTiUlgTlIA3SU .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-xYCoTiUlgTlIA3SU .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-xYCoTiUlgTlIA3SU .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-xYCoTiUlgTlIA3SU .cluster text{fill:#333;}#mermaid-svg-xYCoTiUlgTlIA3SU .cluster span{color:#333;}#mermaid-svg-xYCoTiUlgTlIA3SU div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-xYCoTiUlgTlIA3SU .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-xYCoTiUlgTlIA3SU rect.text{fill:none;stroke-width:0;}#mermaid-svg-xYCoTiUlgTlIA3SU .icon-shape,#mermaid-svg-xYCoTiUlgTlIA3SU .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-xYCoTiUlgTlIA3SU .icon-shape p,#mermaid-svg-xYCoTiUlgTlIA3SU .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-xYCoTiUlgTlIA3SU .icon-shape .label rect,#mermaid-svg-xYCoTiUlgTlIA3SU .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-xYCoTiUlgTlIA3SU .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-xYCoTiUlgTlIA3SU .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-xYCoTiUlgTlIA3SU :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

    👥 团队协作流

    开发者输入需求

    AI 生成 Plan

    📋 方案分享到群

    👀 同事提前 Review

    💬 讨论与调整

    ✅ 确认执行

    🔨 Build 生成代码

    📦 提交 PR,方案附在描述里

    相比"直接丢一堆代码过来让大家猜你改了什么",一份清晰的方案让协作效率直接提升一个档次。

    四、Plan 模式下的最佳实践与进阶技巧

    4.1 怎么写指令,AI 的方案才更靠谱?

    指令质量直接决定了方案质量。经过大量试错,我总结了一个**"四要素"指令公式**:

    [做什么] + [在哪里做] + [有什么约束] + [期望效果]

    举个例子,别写:

    ❌ “加个搜索功能”

    而是写:

    ✅ “在 ProductList.ets 页面顶部添加一个搜索栏,支持关键词模糊搜索商品名称,搜索结果复用现有列表展示,搜索框输入做 300ms 防抖处理,调用 ProductViewModel 中已有的 fetchProducts 方法时传入搜索参数”

    对比一下效果:

    指令质量AI 方案质量需要返工的轮次
    “加搜索” 笼统,可能忽略防抖、复用列表等细节 3-5 轮
    四要素完整指令 精准,覆盖技术选型、组件设计、性能优化 0-1 轮

    4.2 审方案的艺术:不是挑刺,是对话

    经过一段时间的使用,我总结了审方案的四个关键视角:

    视角一:完整性检查

    #mermaid-svg-Zrp5o6qkZf391oaa{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-Zrp5o6qkZf391oaa .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-Zrp5o6qkZf391oaa .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-Zrp5o6qkZf391oaa .error-icon{fill:#552222;}#mermaid-svg-Zrp5o6qkZf391oaa .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-Zrp5o6qkZf391oaa .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-Zrp5o6qkZf391oaa .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-Zrp5o6qkZf391oaa .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-Zrp5o6qkZf391oaa .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-Zrp5o6qkZf391oaa .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-Zrp5o6qkZf391oaa .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-Zrp5o6qkZf391oaa .marker{fill:#333333;stroke:#333333;}#mermaid-svg-Zrp5o6qkZf391oaa .marker.cross{stroke:#333333;}#mermaid-svg-Zrp5o6qkZf391oaa svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-Zrp5o6qkZf391oaa p{margin:0;}#mermaid-svg-Zrp5o6qkZf391oaa .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-Zrp5o6qkZf391oaa .cluster-label text{fill:#333;}#mermaid-svg-Zrp5o6qkZf391oaa .cluster-label span{color:#333;}#mermaid-svg-Zrp5o6qkZf391oaa .cluster-label span p{background-color:transparent;}#mermaid-svg-Zrp5o6qkZf391oaa .label text,#mermaid-svg-Zrp5o6qkZf391oaa span{fill:#333;color:#333;}#mermaid-svg-Zrp5o6qkZf391oaa .node rect,#mermaid-svg-Zrp5o6qkZf391oaa .node circle,#mermaid-svg-Zrp5o6qkZf391oaa .node ellipse,#mermaid-svg-Zrp5o6qkZf391oaa .node polygon,#mermaid-svg-Zrp5o6qkZf391oaa .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-Zrp5o6qkZf391oaa .rough-node .label text,#mermaid-svg-Zrp5o6qkZf391oaa .node .label text,#mermaid-svg-Zrp5o6qkZf391oaa .image-shape .label,#mermaid-svg-Zrp5o6qkZf391oaa .icon-shape .label{text-anchor:middle;}#mermaid-svg-Zrp5o6qkZf391oaa .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-Zrp5o6qkZf391oaa .rough-node .label,#mermaid-svg-Zrp5o6qkZf391oaa .node .label,#mermaid-svg-Zrp5o6qkZf391oaa .image-shape .label,#mermaid-svg-Zrp5o6qkZf391oaa .icon-shape .label{text-align:center;}#mermaid-svg-Zrp5o6qkZf391oaa .node.clickable{cursor:pointer;}#mermaid-svg-Zrp5o6qkZf391oaa .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-Zrp5o6qkZf391oaa .arrowheadPath{fill:#333333;}#mermaid-svg-Zrp5o6qkZf391oaa .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-Zrp5o6qkZf391oaa .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-Zrp5o6qkZf391oaa .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Zrp5o6qkZf391oaa .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-Zrp5o6qkZf391oaa .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Zrp5o6qkZf391oaa .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-Zrp5o6qkZf391oaa .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-Zrp5o6qkZf391oaa .cluster text{fill:#333;}#mermaid-svg-Zrp5o6qkZf391oaa .cluster span{color:#333;}#mermaid-svg-Zrp5o6qkZf391oaa div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-Zrp5o6qkZf391oaa .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-Zrp5o6qkZf391oaa rect.text{fill:none;stroke-width:0;}#mermaid-svg-Zrp5o6qkZf391oaa .icon-shape,#mermaid-svg-Zrp5o6qkZf391oaa .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Zrp5o6qkZf391oaa .icon-shape p,#mermaid-svg-Zrp5o6qkZf391oaa .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-Zrp5o6qkZf391oaa .icon-shape .label rect,#mermaid-svg-Zrp5o6qkZf391oaa .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Zrp5o6qkZf391oaa .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-Zrp5o6qkZf391oaa .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-Zrp5o6qkZf391oaa :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

    开始审方案

    涉及文件列全了吗?

    补充遗漏文件

    实现步骤顺序合理吗?

    调整步骤顺序

    影响分析覆盖了我的顾虑吗?

    追问 AI 补充分析

    代码预览符合团队规范吗?

    在方案上标注规范要求

    ✅ 确认执行

    视角二:业务对齐

    • “AI 理解的需求跟我的真实意图一致吗?”
    • “有没有多做了不需要的事情?”
    • “有没有把简单问题复杂化?”

    视角三:风险预判

    • “列出的影响分析中,有没有我没意识到的隐患?”(这个往往是 AI 比你强的地方)
    • “有没有遗漏的边界条件?”

    视角四:性能与可维护性

    • “生成的代码结构是否清晰?”
    • “是否复用了现有的工具方法?”
    • “有没有引入不必要的依赖?”

    4.3 方案来回调整的最佳节奏

    我摸索出了一个高效的"两轮确认法":

    第一轮:AI 出初版方案 → 我只看"整体方向对不对"
    ├── 方向对 → 第二轮细看
    └── 方向不对 → 一句话告诉 AI 偏哪了,让它重规划

    第二轮:AI 出修正方案 → 我逐条检查细节
    ├── 没大问题 → 确认 Build
    └── 有小问题 → 直接在方案上改,再确认

    最多两轮,绝不陷入"无限拉扯"。如果两轮后方案还不理想,说明你的指令可能需要调整——回头优化指令,比继续跟 AI 来回拉扯更高效。

    4.4 我踩过的坑和总结的经验

    用 Plan 模式大半年来,这些教训是真金白银砸出来的:

    坑 1:方案看着完美就秒点确认

    • 现象:有一次 AI 给的方案非常详细,我一激动直接确认了。结果代码生成后发现,方案里某个步骤引用的 API 在我项目版本里已经被废弃了。
    • 教训:AI 的方案里引用的 API 版本不一定跟你项目的依赖版本一致。遇到不熟悉的 API,方案阶段先去翻一下你的 oh-package.json5 确认版本。

    坑 2:在 Plan 里说"这里改一下",但没说明白怎么改

    • 现象:我在方案上写了"把数据加载部分优化一下",AI 理解成"加缓存",但我想的是"改用分页加载"。
    • 教训:调整指令和初始指令一样,要具体、要四要素。模糊的调整指令 = 新一轮的误解。

    坑 3:不分场景,所有任务都走 Plan

    • 现象:改个变量名都要 Plan → 审方案 → 确认 → Build,效率还不如手动改。
    • 教训:Plan 是用来解决"不确定性"的,不是用来过流程瘾的。

    坑 4:跳过"影响分析"直接看步骤

    • 现象:习惯性只看"实现步骤"就确认,忽略了"影响分析"部分。
    • 教训:影响分析才是 Plan 模式的精华。步骤告诉你"怎么做",影响分析告诉你"做完会怎样"——后者往往是你自己没想到的。

    4.5 小结:一个好方案的"体检清单"

    我把审方案的要点整理成了清单,每次确认前过一遍:

    • 涉及文件是否完整?有没有遗漏?
    • 实现步骤的顺序是否合理?依赖关系对不对?
    • 引用的 API / 组件,在我的项目版本里可用吗?
    • 影响分析有没有提到我没想到的风险?
    • 改动是否最小化?有没有"顺手改了不该改的"?
    • 代码预览的风格是否符合团队规范?
    • 如果涉及性能(防抖、缓存、懒加载),方案有没有覆盖?

    五、Plan+Build 的技术原理与未来展望

    5.1 AI 怎么做到"理解你的项目"?

    你可能会好奇:AI 凭什么能在几秒钟内分析出我的项目结构、找出相关文件、甚至预判到"ViewModel 状态缓存可能不同步"这种级别的风险?

    它的工作流大致是这样的:

    #mermaid-svg-Rn13T7RPkvwkLvib{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-Rn13T7RPkvwkLvib .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-Rn13T7RPkvwkLvib .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-Rn13T7RPkvwkLvib .error-icon{fill:#552222;}#mermaid-svg-Rn13T7RPkvwkLvib .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-Rn13T7RPkvwkLvib .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-Rn13T7RPkvwkLvib .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-Rn13T7RPkvwkLvib .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-Rn13T7RPkvwkLvib .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-Rn13T7RPkvwkLvib .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-Rn13T7RPkvwkLvib .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-Rn13T7RPkvwkLvib .marker{fill:#333333;stroke:#333333;}#mermaid-svg-Rn13T7RPkvwkLvib .marker.cross{stroke:#333333;}#mermaid-svg-Rn13T7RPkvwkLvib svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-Rn13T7RPkvwkLvib p{margin:0;}#mermaid-svg-Rn13T7RPkvwkLvib .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-Rn13T7RPkvwkLvib .cluster-label text{fill:#333;}#mermaid-svg-Rn13T7RPkvwkLvib .cluster-label span{color:#333;}#mermaid-svg-Rn13T7RPkvwkLvib .cluster-label span p{background-color:transparent;}#mermaid-svg-Rn13T7RPkvwkLvib .label text,#mermaid-svg-Rn13T7RPkvwkLvib span{fill:#333;color:#333;}#mermaid-svg-Rn13T7RPkvwkLvib .node rect,#mermaid-svg-Rn13T7RPkvwkLvib .node circle,#mermaid-svg-Rn13T7RPkvwkLvib .node ellipse,#mermaid-svg-Rn13T7RPkvwkLvib .node polygon,#mermaid-svg-Rn13T7RPkvwkLvib .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-Rn13T7RPkvwkLvib .rough-node .label text,#mermaid-svg-Rn13T7RPkvwkLvib .node .label text,#mermaid-svg-Rn13T7RPkvwkLvib .image-shape .label,#mermaid-svg-Rn13T7RPkvwkLvib .icon-shape .label{text-anchor:middle;}#mermaid-svg-Rn13T7RPkvwkLvib .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-Rn13T7RPkvwkLvib .rough-node .label,#mermaid-svg-Rn13T7RPkvwkLvib .node .label,#mermaid-svg-Rn13T7RPkvwkLvib .image-shape .label,#mermaid-svg-Rn13T7RPkvwkLvib .icon-shape .label{text-align:center;}#mermaid-svg-Rn13T7RPkvwkLvib .node.clickable{cursor:pointer;}#mermaid-svg-Rn13T7RPkvwkLvib .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-Rn13T7RPkvwkLvib .arrowheadPath{fill:#333333;}#mermaid-svg-Rn13T7RPkvwkLvib .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-Rn13T7RPkvwkLvib .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-Rn13T7RPkvwkLvib .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Rn13T7RPkvwkLvib .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-Rn13T7RPkvwkLvib .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Rn13T7RPkvwkLvib .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-Rn13T7RPkvwkLvib .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-Rn13T7RPkvwkLvib .cluster text{fill:#333;}#mermaid-svg-Rn13T7RPkvwkLvib .cluster span{color:#333;}#mermaid-svg-Rn13T7RPkvwkLvib div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-Rn13T7RPkvwkLvib .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-Rn13T7RPkvwkLvib rect.text{fill:none;stroke-width:0;}#mermaid-svg-Rn13T7RPkvwkLvib .icon-shape,#mermaid-svg-Rn13T7RPkvwkLvib .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Rn13T7RPkvwkLvib .icon-shape p,#mermaid-svg-Rn13T7RPkvwkLvib .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-Rn13T7RPkvwkLvib .icon-shape .label rect,#mermaid-svg-Rn13T7RPkvwkLvib .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Rn13T7RPkvwkLvib .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-Rn13T7RPkvwkLvib .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-Rn13T7RPkvwkLvib :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

    📤 输出层

    📥 输入层

    🧠 AI 推理引擎

    用户任务描述

    当前打开文件代码

    项目文件结构索引

    依赖配置文件

    项目类型上下文(HarmonyOS / Web / 后端)

    意图解析:提取技术需求关键词

    上下文关联:关联相关文件与模块

    方案生成:规划最优实现路径

    风险评估:基于历史模式匹配常见坑点

    输出格式化:生成结构化方案文档

    结构化方案报告

    分步骤实施计划

    影响分析清单

    代码预览

    重点在于上下文关联这一步。它不是只看你当前打开的 ProductList.ets,而是把整个项目的文件依赖图加载进来:

    ProductList.ets
    ├── import { ProductViewModel } from './ProductViewModel'
    │ └── ProductViewModel.ets
    │ ├── import { ProductApi } from '../api/ProductApi'
    │ │ └── ProductApi.ets ← AI 会读到这里
    │ └── import { ProductModel } from '../models/ProductModel'
    │ └── ProductModel.ets ← AI 也会读到这里
    └── import { LoadingAnim } from '../components/LoadingAnim'
    └── LoadingAnim.ets ← AI 知道这个组件存在

    所以当你让它"加下拉刷新"时,它知道:

    • ProductViewModel 里有数据加载方法,刷新时要调它
    • ProductModel 的结构是什么,数据刷新后怎么重新绑定
    • LoadingAnim 是一个可用组件,可以复用到刷新动画里
    • 上拉加载用的是 onReachEnd,跟 PullToRefresh 不冲突

    这就是 Plan 模式能给出高质量方案的底层逻辑——它不是靠猜,是靠真正"读懂"了你的项目。

    5.2 为什么"审方案"这个环节不可替代?

    有一个观点我想特别强调:Plan 模式让人审方案,不是在浪费你的时间,而是在帮你建立"代码心智模型"。

    #mermaid-svg-pdFsndHa0uzN3CII{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-pdFsndHa0uzN3CII .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-pdFsndHa0uzN3CII .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-pdFsndHa0uzN3CII .error-icon{fill:#552222;}#mermaid-svg-pdFsndHa0uzN3CII .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-pdFsndHa0uzN3CII .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-pdFsndHa0uzN3CII .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-pdFsndHa0uzN3CII .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-pdFsndHa0uzN3CII .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-pdFsndHa0uzN3CII .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-pdFsndHa0uzN3CII .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-pdFsndHa0uzN3CII .marker{fill:#333333;stroke:#333333;}#mermaid-svg-pdFsndHa0uzN3CII .marker.cross{stroke:#333333;}#mermaid-svg-pdFsndHa0uzN3CII svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-pdFsndHa0uzN3CII p{margin:0;}#mermaid-svg-pdFsndHa0uzN3CII .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-pdFsndHa0uzN3CII .cluster-label text{fill:#333;}#mermaid-svg-pdFsndHa0uzN3CII .cluster-label span{color:#333;}#mermaid-svg-pdFsndHa0uzN3CII .cluster-label span p{background-color:transparent;}#mermaid-svg-pdFsndHa0uzN3CII .label text,#mermaid-svg-pdFsndHa0uzN3CII span{fill:#333;color:#333;}#mermaid-svg-pdFsndHa0uzN3CII .node rect,#mermaid-svg-pdFsndHa0uzN3CII .node circle,#mermaid-svg-pdFsndHa0uzN3CII .node ellipse,#mermaid-svg-pdFsndHa0uzN3CII .node polygon,#mermaid-svg-pdFsndHa0uzN3CII .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-pdFsndHa0uzN3CII .rough-node .label text,#mermaid-svg-pdFsndHa0uzN3CII .node .label text,#mermaid-svg-pdFsndHa0uzN3CII .image-shape .label,#mermaid-svg-pdFsndHa0uzN3CII .icon-shape .label{text-anchor:middle;}#mermaid-svg-pdFsndHa0uzN3CII .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-pdFsndHa0uzN3CII .rough-node .label,#mermaid-svg-pdFsndHa0uzN3CII .node .label,#mermaid-svg-pdFsndHa0uzN3CII .image-shape .label,#mermaid-svg-pdFsndHa0uzN3CII .icon-shape .label{text-align:center;}#mermaid-svg-pdFsndHa0uzN3CII .node.clickable{cursor:pointer;}#mermaid-svg-pdFsndHa0uzN3CII .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-pdFsndHa0uzN3CII .arrowheadPath{fill:#333333;}#mermaid-svg-pdFsndHa0uzN3CII .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-pdFsndHa0uzN3CII .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-pdFsndHa0uzN3CII .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-pdFsndHa0uzN3CII .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-pdFsndHa0uzN3CII .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-pdFsndHa0uzN3CII .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-pdFsndHa0uzN3CII .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-pdFsndHa0uzN3CII .cluster text{fill:#333;}#mermaid-svg-pdFsndHa0uzN3CII .cluster span{color:#333;}#mermaid-svg-pdFsndHa0uzN3CII div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-pdFsndHa0uzN3CII .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-pdFsndHa0uzN3CII rect.text{fill:none;stroke-width:0;}#mermaid-svg-pdFsndHa0uzN3CII .icon-shape,#mermaid-svg-pdFsndHa0uzN3CII .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-pdFsndHa0uzN3CII .icon-shape p,#mermaid-svg-pdFsndHa0uzN3CII .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-pdFsndHa0uzN3CII .icon-shape .label rect,#mermaid-svg-pdFsndHa0uzN3CII .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-pdFsndHa0uzN3CII .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-pdFsndHa0uzN3CII .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-pdFsndHa0uzN3CII :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

    Plan 模式的心智路径

    拿到方案

    3 分钟通读

    脑中已有改动地图

    发现 1 个点要调整

    标注后确认

    看着代码按你预期的样子生成

    🧘 认知负载极低

    Direct 模式的心智路径

    拿到代码

    逐行阅读

    推导 AI 的逻辑

    发现 3 个问题

    手动修改

    重新理解自己改了什么

    😵 认知负载极高

    Plan 模式把代码理解从"事后推导"变成了"事前预览"。你不需要先看一堆代码再反推逻辑——你在方案阶段就已经知道了逻辑,代码生成出来只是对你脑中已有模型的确认。

    5.3 未来演进方向

    DevEco Code 的 Plan+Build 模式还在持续迭代,我个人非常期待的演进方向包括:

    1. 方案多版本对比

    📋 方案 A(性能优先) 📋 方案 B(代码简洁优先)
    ───────────────────── ─────────────────────
    使用 List + LazyForEach 使用 Scroll + ForEach
    + 虚拟列表 实现更简单,小数据量
    大数据量场景最优 场景代码更少

    2. 方案评审协作

    方案可以直接生成分享链接,团队成员在方案上评论、点赞、提出修改意见——代码还没写,设计就完成了评审。

    3. 与 DevOps 流程集成

    方案中的"影响分析"可以自动关联到:

    • PR 的检查清单
    • 测试用例的生成建议
    • CI/CD 中需要重点关注的构建步骤

    4. 方案模板与最佳实践库

    团队可以沉淀自己的"方案模板"——比如"如何添加一个新的 API 接口"、“如何接入第三方登录”——Plan 模式会优先参考团队的标准化方案。

    #mermaid-svg-GU6tCo03JmTEN5Bn{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-GU6tCo03JmTEN5Bn .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-GU6tCo03JmTEN5Bn .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-GU6tCo03JmTEN5Bn .error-icon{fill:#552222;}#mermaid-svg-GU6tCo03JmTEN5Bn .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-GU6tCo03JmTEN5Bn .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-GU6tCo03JmTEN5Bn .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-GU6tCo03JmTEN5Bn .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-GU6tCo03JmTEN5Bn .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-GU6tCo03JmTEN5Bn .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-GU6tCo03JmTEN5Bn .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-GU6tCo03JmTEN5Bn .marker{fill:#333333;stroke:#333333;}#mermaid-svg-GU6tCo03JmTEN5Bn .marker.cross{stroke:#333333;}#mermaid-svg-GU6tCo03JmTEN5Bn svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-GU6tCo03JmTEN5Bn p{margin:0;}#mermaid-svg-GU6tCo03JmTEN5Bn .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-GU6tCo03JmTEN5Bn .cluster-label text{fill:#333;}#mermaid-svg-GU6tCo03JmTEN5Bn .cluster-label span{color:#333;}#mermaid-svg-GU6tCo03JmTEN5Bn .cluster-label span p{background-color:transparent;}#mermaid-svg-GU6tCo03JmTEN5Bn .label text,#mermaid-svg-GU6tCo03JmTEN5Bn span{fill:#333;color:#333;}#mermaid-svg-GU6tCo03JmTEN5Bn .node rect,#mermaid-svg-GU6tCo03JmTEN5Bn .node circle,#mermaid-svg-GU6tCo03JmTEN5Bn .node ellipse,#mermaid-svg-GU6tCo03JmTEN5Bn .node polygon,#mermaid-svg-GU6tCo03JmTEN5Bn .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-GU6tCo03JmTEN5Bn .rough-node .label text,#mermaid-svg-GU6tCo03JmTEN5Bn .node .label text,#mermaid-svg-GU6tCo03JmTEN5Bn .image-shape .label,#mermaid-svg-GU6tCo03JmTEN5Bn .icon-shape .label{text-anchor:middle;}#mermaid-svg-GU6tCo03JmTEN5Bn .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-GU6tCo03JmTEN5Bn .rough-node .label,#mermaid-svg-GU6tCo03JmTEN5Bn .node .label,#mermaid-svg-GU6tCo03JmTEN5Bn .image-shape .label,#mermaid-svg-GU6tCo03JmTEN5Bn .icon-shape .label{text-align:center;}#mermaid-svg-GU6tCo03JmTEN5Bn .node.clickable{cursor:pointer;}#mermaid-svg-GU6tCo03JmTEN5Bn .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-GU6tCo03JmTEN5Bn .arrowheadPath{fill:#333333;}#mermaid-svg-GU6tCo03JmTEN5Bn .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-GU6tCo03JmTEN5Bn .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-GU6tCo03JmTEN5Bn .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-GU6tCo03JmTEN5Bn .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-GU6tCo03JmTEN5Bn .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-GU6tCo03JmTEN5Bn .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-GU6tCo03JmTEN5Bn .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-GU6tCo03JmTEN5Bn .cluster text{fill:#333;}#mermaid-svg-GU6tCo03JmTEN5Bn .cluster span{color:#333;}#mermaid-svg-GU6tCo03JmTEN5Bn div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-GU6tCo03JmTEN5Bn .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-GU6tCo03JmTEN5Bn rect.text{fill:none;stroke-width:0;}#mermaid-svg-GU6tCo03JmTEN5Bn .icon-shape,#mermaid-svg-GU6tCo03JmTEN5Bn .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-GU6tCo03JmTEN5Bn .icon-shape p,#mermaid-svg-GU6tCo03JmTEN5Bn .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-GU6tCo03JmTEN5Bn .icon-shape .label rect,#mermaid-svg-GU6tCo03JmTEN5Bn .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-GU6tCo03JmTEN5Bn .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-GU6tCo03JmTEN5Bn .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-GU6tCo03JmTEN5Bn :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

    未来方向

    多版本方案对比

    团队协作评审

    DevOps 集成

    方案模板库

    方案自动生成测试用例

    当前能力

    单次任务 Plan

    项目上下文分析

    影响分析

    结语

    Plan+Build 这个模式用了一段时间,我最大的感受是:它把 AI 从一个"帮你敲字的实习生",变成了一个"先跟你对方案再动手的高级搭档"。

    以前用 AI 写代码,经常是"惊喜"和"惊吓"交替——有时候惊艳,更多时候是在 debug 一段自己没看懂的逻辑。现在 Plan 模式让整个过程变得可预期、可干预、可信任。

    最后给你留一道"自测题",判断你是否已经掌握了 Plan 模式的精髓:

    下次接到一个新需求,在打开编辑器之前,先问自己三个问题:

  • 这个需求涉及几个文件?— 超过 1 个 → Plan
  • 我对这块代码的完整逻辑有 100% 把握吗?— 没有 → Plan
  • 改完之后,我能确定没有遗漏的副作用吗?— 不能 → Plan
  • 只要有一个答案让你犹豫——先 Plan,再 Build。

    如果你也用 DevEco Code,试一下这个模式。尤其是下次碰到一个看起来"挺简单但突然变复杂了"的需求的时候——相信我,你会回来点赞的。

    赞(0)
    未经允许不得转载:网硕互联帮助中心 » DevEco Code Plan+Build模式:审方案再执行,提升开发效率与质量
    分享到: 更多 (0)

    评论 抢沙发

    评论前必须登录!