咔搭KaDa 软件说明书
拖拽搭建 · 导出 Flutter 工程 · 本地离线运行
第一章 产品概述
1.1 一句话定位
咔搭KaDa(技术代号 Visual App Builder,简称 VAB)是一款本地运行、离线优先、Flutter 优先的桌面低代码应用开发平台。它把「拖拽组件 → 生成 Schema → 生成 Flutter 工程 → flutter run 成功」这条链路收进一个窗口,让没有 Flutter 经验的人也能在几分钟内得到一个可以安装到手机上运行的应用。
1.2 产品口号
Build Once. Export Anywhere. —— 一次设计,随处运行。
1.3 版权归属
| 项 | 内容 |
|---|---|
| 软件名称 | 咔搭KaDa(Visual App Builder),技术代号 VAB |
| 版权归属 | 飞翔的死猪 |
| 版本 | V1.0(Schema 协议版本 1.0) |
| 运行方式 | Windows 桌面应用,本地离线运行,无需联网、无需账号 |
软件内「帮助 → 关于」页、欢迎页页脚与安装包元数据(发布者字段)均标注同一归属。
1.3 核心设计哲学
- Schema 是唯一真相源:画布、组件树、属性面板、代码区、生成器、导出器全部读写同一份 Schema,不存在第二份可漂移的副本。
- 画布所见 = 导出所得:布局语义在 Kotlin 布局引擎、Flutter 代码生成器、前端画布三方逐字同源,任何改动必须同步三处。
- 画布与代码互相修正:画布是入口,代码也是入口,两个方向都能定位与回写。
- 离线优先:运行期零外部网络请求,无账号、无遥测、无 CDN。
1.4 目标用户
| 用户类型 | 画像描述 | 典型用法 |
|---|---|---|
| 个人开发者 / 独立开发者 | 熟悉代码,把 VAB 当可视化脚手架 | 画布搭骨架,切到代码区精修,导出后接手开发 |
| 学生 / 学习者 | 想快速做出一个能跑的 App | 拖拽完成课程设计 / 竞赛原型,直接 flutter run |
| 小型团队 / 工作室 | 1 名开发 + 产品 / 设计 | 设计侧出页面结构,开发侧接手导出工程 |
| 业务人员 | 非程序员,想自己拖出内部工具 | 只用画布与属性面板,遇错看提示 |
1.5 产品边界(明确不做)
以下内容不在当前版本范围内,任何形式的「顺手做了」都视为范围膨胀:
- AI 生成页面 / AI 布局优化 / AI 代码生成
- 云同步 / 云存储 / 云备份;用户账号 / 登录 / 会员
- 多人协作 / 实时协同 / 在线编辑;工作流引擎 / 后端服务
- 插件市场 / 在线下载插件
- ArkUI / React / Vue / 小程序 / Electron 导出
- Figma / Sketch 导入
1.6 系统要求
| 项目 | 要求 |
|---|---|
| 操作系统 | Windows 10 1809 或更高版本 / Windows 11,x64 |
| WebView2 运行时 | Win11 自带;Win10 需安装 Evergreen 版 |
| Java 运行时 | 无需安装:交付包内已捆绑 jlink 裁剪后的 JRE |
| 内存 / 磁盘 | 建议 4 GB 以上;约 200 MB 可用空间 |
| Flutter SDK | 可选:仅「构建 APK / dart analyze」等真机调试功能需要 |
| 网络 | 运行期完全不需要联网 |
第二章 安装与首次运行
2.1 交付形态
本版本为免安装目录版,解压即用,不需要管理员权限,也不写注册表。交付目录结构:
VisualAppBuilder/ ├── VisualAppBuilder.exe ← 双击启动(WebView2 外壳 + VAB 图标) ├── *.dll / WebView2Loader.dll ← 外壳与 WebView2 加载器 ├── 首次运行说明.txt ← SmartScreen 说明(建议先读) ├── app/visual-app-builder-all.jar ← Kotlin 宿主(业务全在这里) ├── app/app.jsa ← AppCDS 启动归档(约 24 MB) ├── runtime/ ← jlink 裁剪的 JRE(用户不必装 Java) ├── logs/ ← 宿主日志(排障时最重要) ├── plugins/ ← 第三方插件 jar 放这里 └── plugin-settings.json ← 插件禁用与授权记录
2.2 首次运行可能看到的弹窗
第一次双击 VisualAppBuilder.exe 时,Windows 可能弹出「Windows 保护了你的电脑 / Microsoft Defender SmartScreen」。这不是病毒,也不是程序出错:安装包没有购买代码签名证书,Windows 按「未知应用」处理。
根治办法是代码签名(EV 证书或 Azure Trusted Signing)。发布方执行:
gradlew :app:packageShell -PsignPfx=<证书.pfx> -PsignPassword=<密码>
2.3 启动流程
- 外壳(VisualAppBuilder.exe)显示「正在启动本地服务…」遮罩,并在后台拉起 Kotlin 宿主进程。
- 宿主启动本地 HTTP 服务(仅监听 127.0.0.1,随机端口),扫描插件目录,加载上次记忆的工程目录。
- 宿主在标准输出打印带 32 位会话令牌的本地地址,外壳解析后交给 WebView2 加载。
- 页面加载完成,遮罩消失,出现欢迎页。
实测耗时:宿主就绪 411–550 ms,窗口显示到页面导航完成约 1400 ms。
2.4 程序会在哪里写文件
- EXE 同级目录:
logs/(宿主日志)、WebView2/(浏览器缓存)、plugin-settings.json。 - 写不进去时自动退到
%LOCALAPPDATA%\VisualAppBuilder。 - 你的工程目录:只有你明确点「保存」或「导出」时才会写入。
~/.vab/preferences.json:记住上次使用的工程目录与导出目录。
2.5 卸载
直接删除整个 VisualAppBuilder 目录即可。如需彻底清理,再删除 %LOCALAPPDATA%\VisualAppBuilder 与 ~/.vab。
第三章 三分钟跑通主链路
第一次使用建议按下面六步完整走一遍。走完这一遍,主链路就通了,后面都是细节。
3.1 新建项目
菜单「文件 → 新建项目…」(或欢迎页的「新建项目」按钮)→ 在弹出的原生目录选择器里选一个空目录 → 填写项目名 → 确认。
新建出来的工程是一个空白页:只有一个页面根容器,没有任何预置示例组件 —— 你从一开始就在自己的工程里。
3.2 拖一个组件
在左栏「组件库」里按住一个组件(例如 Button),拖到中间画布,松手。拖进来后组件会自动被选中,右栏属性面板立刻显示它的属性。
3.3 改属性
点画布上的按钮 → 右栏「属性面板」把「文本内容」改成「去设置」。看不到属性面板时,用「视图 → 属性面板」打开。
3.4 再建一页
菜单「页面 → 新建页面」,在第二页放一个 Text 组件,写上「这是设置页」。
3.5 把两页连起来
画布工具条点「连接页面」→ 在画布上点一下刚才的按钮(① 选中源)→ 逻辑类型保持「页面跳转」→ 点右侧的目标页面「设置页」。连上后,画布上按钮右上角会出现「→ 设置页」角标。
3.6 导出并运行
菜单「文件 → 导出 Flutter 工程…」→ 选择导出目录 → 等待完成 → 点「打开导出目录」。在导出目录执行:
flutter pub get flutter run
手机 / 模拟器上出现你做的页面,点按钮能跳到第二页 —— 主链路完成。
第四章 界面地图
| 区域 | 位置 | 怎么打开 | 作用 |
|---|---|---|---|
| 菜单栏 / 工具栏 | 顶部 | 常显 | 文件 / 编辑 / 页面 / 视图 / 帮助五组菜单;右侧是撤销重做、缩放、设备档位、主题、视图模式 |
| 组件库 | 左栏上半 | 视图 → 组件库 / 组件树 | 拖拽来源;支持搜索;按 10 个分类分组,默认展开「基础」 |
| 组件树 | 左栏下半 | 同上 | 当前页面的层级;点树里的节点 = 选中画布元素;可拖拽改父子关系 |
| 画布 | 中间 | 常显 | 摆放 / 拖动 / 对齐 / 框选;顶部有缩放、设备档位、吸附开关、连接页面开关 |
| 属性面板 | 右栏 | 视图 → 属性面板 | 选中元素的全部属性:文本、尺寸、间距、颜色、圆角、动效、交互 |
| 代码区 | 右侧或独占 | 视图 → 代码区 | 生成的 Dart 源码(Monaco);与画布双向定位 |
| 调试面板 | 代码视图右栏 | 切到「代码」视图 | 目标设备、一键运行、分步结果、logcat、截图、内置终端 |
| 输出面板 | 底部 | 视图 → 输出面板 | 宿主日志、导出结果、运行输出 |
| 状态栏 | 底部 | 常显 | 项目名、Schema 版本、保存态、当前页、选中数、缩放、布局模式、诊断计数、SSE 连接 |
| 连接器 | 画布右下浮层 | 画布工具条「连接页面」 | 接线图:页面跳转 / 数据流 / 事件触发的唯一编辑入口 |
4.1 三种视图模式
| 模式 | 顶栏按钮 | 适用场景 |
|---|---|---|
| 画布独占(默认) | ▦ 画布 | 专注拖拽,所见即所得 |
| 左右分屏 | ⫿ 拆分 | 画布在左、代码在右,两条入口同时可见,互相修正 |
| 代码独占 | 𝟙 代码 | 专注看 / 改代码,看不到画布 |
视图选择会被记住,下次打开仍停在你上次选的模式。
4.2 布局会自适应窄窗口
窗口不够宽时,软件按固定优先级让位:属性栏与画布永不被牺牲,左栏与代码区可自动收起。窗口变宽后面板会自己回来,不会写回你的偏好设置。
第五章 画布操作详解
5.1 选中
| 想做的事 | 怎么做 |
|---|---|
| 选中单个元素 | 在画布上单击它;或点组件树里的对应节点 |
| 加选多个 | Shift + 单击;或 Ctrl + 单击(再点一次取消) |
| 框选多个 | 在空白处按住拖拽,画框覆盖 |
| 全选同层 | Ctrl+A(有选中时选它的全部兄弟;无选中时选当前页顶层全部) |
| 取消选择 | Esc 或点空白处 |
5.2 移动与摆放
直接拖动元素即可。拖动时会出现参考线并与同级节点 / 页面框的边和中心自动吸附,位置更整齐。吸附可以在画布的「吸附 开/关」chip 上临时关掉,按住 Alt 也可以临时关闭。
选中后拖动八个方向的手柄可以缩放。页面框本身也可以拖右下角把手改变预览尺寸(只影响预览,不影响导出)。
5.3 对齐与分布
多选两个以上元素后,用工具栏的六向对齐按钮(左 / 水平居中 / 右 / 上 / 垂直居中 / 下)或右键菜单。
分布分两种:等距(需选中 3 个以上,首尾固定)与拉伸(需选中 2 个,统一为最大尺寸)。
5.4 层级调整
| 操作 | 快捷键 | 说明 |
|---|---|---|
| 上移 / 下移 | Ctrl+[ / Ctrl+] | 在同一父容器内移动一位 |
| 置顶 / 置底 | Ctrl+Shift+[ / ] | 移到最前 / 最后 |
5.5 复制 / 剪切 / 粘贴
| 操作 | 快捷键 | 说明 |
|---|---|---|
| 复制 | Ctrl+C | 复制选中节点(含整棵子树) |
| 剪切 | Ctrl+X | 复制后删除 |
| 粘贴 | Ctrl+V | 粘贴到当前选中容器的下一位;支持跨页面粘贴 |
| 原地复制 | Ctrl+D | 在同一父容器内复制一份 |
粘贴出来的节点会被分配全新的全局唯一 ID,不会与原节点冲突或串数据。
5.6 撤销与重做
Ctrl+Z 撤销,Ctrl+Y(或 Ctrl+Shift+Z)重做。撤销覆盖拖动、删除、属性修改、多选操作、粘贴、层级调整、以及代码区的手改 —— 画布与代码共用同一条历史栈。
菜单与工具栏会显示「撤销:插入 Button」这样的操作名,你不必先撤了才知道撤的是什么。
5.7 锁定
Ctrl+B 锁定 / 解锁。锁定后节点仍然渲染、仍然出现在组件树里,但画布上不能拖动、不能删除、属性只读。锁定的目的是防止手滑,不是把节点藏起来。
5.8 隐藏
选中节点后用工具栏的 🙈 按钮、右键菜单或属性面板头部的「隐藏」按钮。
隐藏的节点在画布上只留一个半透明「已隐藏」幽灵占位(布局与命中测试都会跳过它),但仍然在 Schema 与组件树里,在组件树行尾打「隐藏」标识。恢复显示:在组件树里选中该节点,再点一次「显示」。
5.9 定位到代码
选中元素后按 F2(或右键「定位到代码」):代码区会自动弹出并跳到该元素对应的 Widget。如果你当前在画布独占模式,软件会自动切到左右分屏,让画布和代码同时可见。
5.10 两种布局模式
| 模式 | 状态栏显示 | 说明 |
|---|---|---|
| 自由定位 | 自由定位 | 顶层元素各自带坐标,随意摆放;切到别的设备档时坐标独立(可分别摆放) |
| 流式布局 | 流式布局 | 顶层元素按 Column / Row 顺序排列,不设坐标 |
新建页面默认是自由定位。第一次把组件拖进根容器时,落点坐标会写进 Schema,页面即进入自由定位模式。
第六章 页面管理
6.1 页签栏
画布上方是页签栏,显示当前工程的所有页面。点页签切换页面;双击页签可以重命名;页签上的 × 删除页面(至少保留一页)。页签栏右端是「起始页」下拉,选择 App 打开时进入的页面。
6.2 页面菜单
- 页面 → 新建页面:新建一页,默认自由定位。
- 页面 → 上一页 / 下一页(Ctrl+Tab / Ctrl+Shift+Tab):环形切换。
- 页面 → 当前:xxx(信息行,告诉你删的是哪一页)。
- 页面 → 删除当前页面:只剩一页时禁用,鼠标悬停会显示「至少保留一页」。
6.3 页面 id 与文件名的关系
每个页面在导出工程里对应一个 Dart 文件:页面 id 会翻译成 PascalCase 类名与 snake_case 文件名。例如页面 home 生成 HomePage 类与 lib/pages/home_page.dart。因此页面 id 一经使用不建议更改。
6.4 起始页与可达性
新页面默认没有任何入口。连接器面板顶部会在「有 N 个页面从起始页走不到」时给出告警 —— 这是提醒你去连一条跳转,不是报错。所有页面都能从起始页走到时显示绿色的 ✓。
第七章 接线(核心能力)
接线是 VAB 与普通拖拽工具最大的区别:它让「页面之间、组件之间真的有逻辑关系」,而且这些关系会原样落到导出的 Flutter 工程里,不是画在图上的装饰。
7.1 打开连接器
画布工具条点「连接页面」→ 画布右下角出现连接器面板。面板右下角有把手,拖拽可以改变大小,尺寸会被记住。
7.2 三步建立一条连接
- ① 选源元素:在画布上点一下要做连接的源元素(按钮、图标按钮、FAB、列表项、胶囊、导航类组件)。连接模式开着时,点节点只选源、不会拖动。
- ② 选逻辑类型:页面跳转 / 数据流 / 事件触发。
- ③ 点目标:页面跳转点目标页面(或目标页面里的某个具体元素),数据流 / 事件触发点页面或组件。
7.3 三类逻辑
| 类型 | 颜色 | 语义 | 导出产物里是什么 |
|---|---|---|---|
| 页面跳转 navigate | 蓝 | 点元素 → 去某页 | context.go('/目标页');带元素定位时追加 ?focusedNode=<元素id> |
| 数据流 data | 绿 | 源控件的值 → 目标元素显示 | VabWireStore 值总线 + 目标元素订阅 |
| 事件触发 event | 橙 | 点 / 变更源 → 目标滚动入屏并聚焦 | VabWireBus.fire(...) + VabWireTarget 包裹 |
| 断线 dangling | 红 | 目标页 / 组件已被删除 | 导出时告警,不生成非法跳转 |
7.4 元素级定位(跳到某页的某个元素)
在③里选「目标页里的某个元素」而不是页名。导出产物会带 ?focusedNode=<元素id>,目标页据此把那个元素滚动到视野内并聚焦(如果是输入框,还会把键盘焦点交给它)。
典型场景:点「设置」直接落在设置页的「账号安全」这一行。
7.5 导航组件必须逐项绑定
底部导航 / 侧边导航 / 页签是多项控件:一个组件一条边表达不了「第 2 项去设置页」。
因此选中这类源元素后,③-1 会列出每一项。先点其中一项(例如「设置」),再点目标页面,只连这一项。已连的项显示 ✓。连接明细里每条逐项连接单独一行,点「断开」只断那一项。
onTap(i) 按下标分派,绑整体在产物里无法表达「点哪项去哪」,软件会明确拦住并说明原因。旧工程里的整组件绑定会被兼容解释为「所有项都跳该页」并给出告警。7.6 自由连线
面板上「自由连线 开」→ 在接线图里从一个节点直接拖到另一个节点。跳转只能落在页面上(拖到组件上不会生成非法跳转),数据 / 事件可以落在任意节点。
7.7 怎么确认「真的连上了」
| 现象 | 含义 |
|---|---|
| 元素右上角「→ 目标页」角标 | 该元素有跳转,且目标页存在 |
| 角标变红 / 接线图红色虚线 | 断线:目标页已被删,导出时会告警 |
| 面板底部「⚠ 有 N 个页面从起始页走不到」 | 那些页面没有入口,用户永远到不了 |
7.8 接线在导出产物里长什么样
| Schema 里的形状 | 导出产物 |
|---|---|
event.onClick[{action: navigate, target}] | context.go('/目标') |
event.onClick[{action: navigate, target, targetNodeId}] | context.go('/目标?focusedNode=元素id') |
itemTargets[i] | 逐项跳转的常量表 + 下标越界保护 |
wireLinks[{type: data, target}] | VabWireStore 读写 |
wireLinks[{type: event, target}] | VabWireBus.fire(...) |
运行期实现集中在导出工程的 lib/wiring/vab_wiring.dart,并随产物附带一份 test/wiring_behavior_test.dart(用真实 Flutter 引擎验证「点了真的跳、数据真的流、焦点真的给」)。
第八章 动效配置
8.1 基础入场动画
选中元素 → 属性面板的「动画」分组。每个组件都有这一组属性:
| 属性 | 可选值 | 说明 |
|---|---|---|
| 类型 | 无 / 淡入 / 滑动 / 缩放 / 浮起 / 弹性回弹 / 旋进 / 翻转进入 / 生长 / 错峰 / 强调显现 | 命名对齐视觉现象,按观感找 |
| 时长(ms) | 数字 | 默认 300 |
| 缓动曲线 | 线性 / 缓动 / 缓入 / 缓出 / 缓入缓出 / 减速 / 过冲 / 强调减速 / 快出慢入 | 与 Flutter Curves 逐一对应 |
| 滑动方向 | 左 / 右 / 上 / 下 | 仅滑动类动画使用 |
| 起始缩放 | 0.0~1.0 | 仅缩放类使用 |
| 位移距离(px) | 数字 | 仅滑动类使用 |
| 错峰间隔(ms) | 数字 | 仅错峰类型使用 |
8.2 动效组件(拖入即带编排动效)
组件库的「动效」分类下有 12 个预设组件:脉冲、呼吸、漂浮、流光、心跳、摇摆、霓虹呼吸、跑马灯、弹入卡片、滑入卡片、翻转卡片、打字机文本。拖进来就带一段编排好的动效,可直接改参数。
8.3 动画编排
选中元素后用「动画编排」面板可以增删改多条动效。每条动效有触发器(入场 / 点击 / 悬停 / 循环)与多条并行轨道(位移 / 缩放 / 透明度 / 背景色 / 旋转 / 模糊),各轨道独立带时长、延迟与缓动。
8.4 所见即所得
画布预览与导出产物共用同一套数值(类型、时长、缓动、距离、错峰序号逐字同源),不会出现「预览一个样、导出另一个样」。导出产物用 TweenAnimationBuilder 包裹。
第九章 代码区与诊断
9.1 代码区
代码区展示的是生成的 Dart 源码(只读对照)。左侧是竖向文件树,点哪个文件就在右侧打开它。Monaco 编辑器支持查找、折叠、语法高亮、格式化(Shift+Alt+F)。
Monaco 是懒加载的:第一次打开代码区时才下载解析,首屏因此只占约 359 KB。
9.2 画布 ↔ 代码双向定位
| 方向 | 怎么做 | 结果 |
|---|---|---|
| 画布 → 代码 | 选中元素按 F2 / 右键「定位到代码」 | 代码区弹出并跳到该 Widget,高亮对应行 |
| 代码 → 画布 | 在代码区把光标点到某个 Widget 行 | 画布自动选中对应节点 |
9.3 诊断
诊断分两层:
- L1 前端语法检查:你打字时即时给出未闭合括号 / 引号、缺分号等标记(编辑器里直接画波浪线)。
- L3 后端检查:Schema 级与生成代码级的问题(如未定义标识符、悬空跳转目标),集中在「问题」面板。
状态栏的「⛔ n ⚠ n」与问题面板条目数严格相等。诊断只警告、不阻断导出 —— 你不会因为一个 warning 而无法交付。
9.4 手改代码的保护
如果你在导出工程里手改了生成的文件,再次导出时该文件会被保留(不覆盖你的修改),新版内容存到 .vab/conflicts/<路径>.new 供你对比合并。lib/widgets/ 目录是你的地盘,生成器永不写入。
导出完成面板会明确列出「保留 N 个」与「冲突已备份 N 个」,不会静默。
第十章 预览与导出
10.1 设备档位
顶栏右侧切手机 ▯ / 平板 ▭ / 桌面 ▬。画布按档位渲染,设备框会自动居中。自由定位下三端坐标各自独立:在手机上摆的位置不会覆盖平板上摆的位置;某设备还没摆过时沿用其它档的位置,切档不会造成位移。
10.2 页面背景色
在属性面板可以改当前页的页面底色(根容器的 pageBackground)。导出侧由 Scaffold.backgroundColor 接住,所见即所得。
10.3 导出
菜单「文件 → 导出 Flutter 工程…」→ 选择目标目录 → 等待完成。导出面板会显示:
- 进度条与阶段文案(生成 Dart 源码 → 写入磁盘工程)。
- 导出目录(无论成败都显示,失败时你需要它去手工排查)。
- 写入 / 冲突已备份 / 保留 / 拒绝 / 警告 五个计数。
- 完整的保留、拒绝、警告清单(不截断)。
- 「打开导出目录」按钮(成功后可直接跳到生成物)。
10.4 导出结论的三档语义
导出结果不是简单的「成功 / 失败」,而是三个正交判据:
| 档位 | 结论文案 | 下一步 |
|---|---|---|
| 全部就绪 | 导出完成:N 个文件 | 可以直接 flutter pub get && flutter run |
| 资源不完整 | 导出完成,但资源不完整:图片可能加载失败 | 按下方警告补齐源文件后重新导出;若尚未打开工程,先保存或打开工程 |
| 工程不可运行 | 导出失败:工程不可运行(缺少 pubspec 等必需文件) | 换一个空的导出目录后重试(补图救不了它) |
为什么拆三档:缺几张图和工程根本跑不起来是两件完全不同的事,处置方式也完全不同。把两者压成同一句「失败」等于把判断责任推给你。
10.5 导出产物结构
导出目录/ ├── pubspec.yaml ← 依赖(go_router)+ assets 登记 ├── analysis_options.yaml ├── lib/ │ ├── main.dart ← 入口,挂 app_router │ ├── pages/<每页一个文件>.dart ← 页面与组件 │ ├── wiring/vab_wiring.dart ← 接线运行时(总线 + 目标包裹) │ ├── theme/app_theme.dart │ └── navigation/app_router.dart ├── test/wiring_behavior_test.dart ← 接线行为测试(可选跑) ├── android/ ios/ ← 平台桩(本机有 Flutter 时自动补齐) └── assets/ ← 你导入的图片
10.6 二次导出不丢手写代码
lib/widgets/ 与你接管过的区块会被保留;android/ 与 ios/ 生成器不碰。没有接线的工程,导出产物与引入接线能力之前逐字节一致(有金标准哈希护栏守着)。
10.7 本机没装 Flutter 时
导出仍然可以完成(lib/、pubspec、资源都写出),但 android/ios 平台桩无法自动补齐,会给出可照抄的手动命令:
flutter create --empty --no-pub --platforms=android,ios .
第十一章 真机 / 模拟器调试
11.1 打开调试面板
切到「代码」视图 → 右栏就是调试面板(与内置终端并列)。
11.2 两种目标模式
| 内置模拟器(省心) | 真机(自己负责连接) | |
|---|---|---|
| 起模拟器 | 自动(仅当没有在线设备时) | 不做 —— 连接是你自己的事 |
| 等启动 | 自动轮询到设备就绪(4 分钟上限) | 不做 |
| 缺前置条件 | 在按之前就给出可照抄的命令 | 给连接指引(USB 调试 / 授权框) |
11.3 一键运行
点「一键运行」后,软件按步骤执行:选设备 → 构建 APK → 安装 → 启动 → 开日志。每一步在面板里都有 ✓ / ✗ / … / – 与理由 —— 构建可能要几分钟,只转圈你会以为它死了,把每一步摆出来等于让软件自述它正在替你做什么。
11.4 面板提供的能力
- 运行 / 停止应用、安装 APK。
- logcat 实时日志流(按 200 ms 攒批推送,面板不卡)。
- 崩溃自动检测:直接从洪流里挑出 FATAL EXCEPTION / ANR 等行,你不用自己翻。
- 启动状态检测:系统打出
Displayed <包名>才算真的起来了。 - 一键截图(返回 PNG 直接看)。
- 模拟输入:点击 / 滑动 / 按键 / 输入文本。
- 内置终端:
flutter --version / devices / doctor / build / analyze等白名单命令。
11.5 环境要求
- 真机:Android SDK 平台工具(adb)+ 手机开 USB 调试并在弹窗授权。
- 模拟器:Android SDK 的 emulator + 至少一个 AVD。
- 构建 APK:本机安装 Flutter SDK(首次构建需要联网拉依赖)。
缺前置条件时,按钮会提前置灰并说明缺什么,不会让你跑到一半读一句费解的构建失败。
第十二章 效率与个性化
12.1 命令面板
Ctrl+P 打开命令面板搜命令。菜单里有的,面板里都能搜到 —— 两者读的是同一份菜单定义,「菜单里有、面板搜不到」在结构上不可能发生。
12.2 快捷键一览与改键
「帮助 → 键盘快捷键…」打开一览表。表里的键位可以直接改:点「改键」然后按下想用的组合即可,改动会记住(存本机 localStorage),也可以一键全部恢复默认。改键时会检测冲突并提示。
12.3 主题
顶栏右侧切换浅色 / 暗色主题,默认跟随系统。代码区配色与界面同源,切主题时一起变。
注意:这里的主题是编辑器界面的明暗;导出工程的 AppTheme 颜色在右栏顶部的「应用主题」折叠面板里改,是两件事。
12.4 应用主题(导出工程的配色)
右栏顶部的折叠面板里可以改 5 个颜色:主色 / 次色 / 第三色 / 表面色 / 错误色,以及字体。这些值直接进导出工程的 lib/theme/app_theme.dart。
12.5 布局记忆
面板宽度、开合、缩放、连接器尺寸、视图模式都会被记住。「视图 → 恢复默认布局」一键还原。
12.6 新手教程
「帮助 → 新手教程…」(欢迎页右上角也有按钮)。教程不是一篇静态文章:
- 「去操作」直接执行真实动作(打开连接器 / 调试面板 / 新建页面 / 导出…),与手点菜单完全等价。
- 「定位」把真实控件高亮并滚动到视野内。
- 可以勾选「已完成」记录进度(本地状态,不进工程)。
第十三章 插件系统
13.1 插件能提供什么
- 第三方组件(进组件库、画布、属性面板、生成器)。
- 生成器扩展 / 主题扩展。
- 内置示例:
plugins/glass-card(玻璃卡片组件)。
13.2 怎么装
把插件 jar 放进程序目录的 plugins/ 子目录,重启咔搭KaDa 即被发现。
13.3 怎么管理
「帮助 → 插件…」(或 Ctrl+P 搜「插件」)打开插件面板,可以看到:
- 每个插件申请了哪些能力、批没批。
- 贡献了哪些组件。
- 加载失败的原因(清单不对、jar 里误打包宿主类、onLoad 抛异常都会写明)。
- 被你禁用的列表(单独分区,不会和「坏了」混在一起)。
13.4 危险能力默认拒绝
基础能力(注册组件 / 生成器 / 主题 / 读 Schema)自动授予;读写文件、联网、执行进程默认拒绝,只在面板里点过「授权」才生效,且下次启动才应用。授权记录在 exe 同级的 plugin-settings.json,删掉它就回到全部拒绝。
13.5 当前限制
- 还没有每插件配置界面。
- 没有插件热重载:改完权限要重启。
- 第三方插件的真实兼容性只验证过一个示例插件。
13.6 想写插件
参考仓库里的 docs/26_插件作者指南.md:清单字段、三个致命细节、能力白名单、生命周期、失败路径速查、发布自查清单,并可用 vab-plugin-verify 自检。
第十四章 快捷键速查表
| 功能 | 快捷键 | 作用域 |
|---|---|---|
| 保存项目 | Ctrl+S | 全局(焦点在代码区时为保存文件) |
| 撤销 / 重做 | Ctrl+Z / Ctrl+Y(或 Ctrl+Shift+Z) | 全局 |
| 复制 / 剪切 / 粘贴 / 原地复制 | Ctrl+C / X / V / D | 画布 / 组件树 / 属性面板 |
| 删除 / 取消选择 | Delete / Esc | 画布 / 组件树 / 属性面板 |
| 全选同层 | Ctrl+A | 画布 / 组件树 / 属性面板 |
| 锁定 / 解锁 | Ctrl+B | 画布 / 组件树 / 属性面板 |
| 定位到代码 | F2 | 画布 / 组件树 / 属性面板 |
| 上移 / 下移 / 置顶 / 置底 | Ctrl+[ / ] / Ctrl+Shift+[ / ] | 画布 / 组件树 / 属性面板 |
| 放大 / 缩小 / 100% / 适应窗口 | Ctrl++ / - / 0 / 1 | 全局 |
| 下一页 / 上一页 | Ctrl+Tab / Ctrl+Shift+Tab | 全局 |
| 命令面板 | Ctrl+P | 全局 |
| 格式化文件 | Shift+Alt+F | 代码区 |
在输入框里打字时,剪贴板与撤销类快捷键会让位给文本编辑(Esc 除外)。
第十五章 常见问题(FAQ)
导出后运行,点按钮没反应?
先看按钮右上角有没有「→ 目标页」角标。没有 = 没连线(去连接器连一条);有但角标是红的 = 目标页被删了。
导航条(底部导航 / 侧边栏 / 页签)怎么连?
这三类组件只能逐项连:在连接器里先在 ③-1 选中要连的那一项,再点目标页面。它们按条目分派(点哪项去哪),所以不能绑定「整个组件」—— 这是刻意限制,防止出现「绑了却点不动」的无效连接。
连接器面板挡住画布 / 太小?
拖右下角把手改大小(会记住);也可以先关掉连接器,画布工具条随时能开回来。
想跳到目标页里的某一行,找不到那个元素?
目标元素列表列的是该页全部节点(含 Text、容器等非交互元素),直接用搜索框搜名字;选中后产物会滚动并聚焦过去。
文件选择器点了没反应 / 很慢?
对话框是宿主(另一个进程)弹出的系统原生长框,已做置顶、居中与预热。首次弹出若仍略慢,是系统在枚举 Shell 目录(OneDrive / 网络盘)。
第一次运行弹出「Windows 保护了你的电脑」?
不是病毒。安装包没有代码签名证书,Windows 按未知应用处理。点「更多信息 → 仍要运行」即可,只需一次。详见 EXE 同级的 首次运行说明.txt。
启动慢?
这一版做了四件事:① 移除内嵌 Chromium(fatJar 253 MB → 81 MB);② AppCDS 归档(宿主就绪从约 1.1 s 降到 0.41–0.53 s);③ 启动参数调优;④ Monaco 懒加载(打开代码区时才下载,首屏体积降 89%)。
界面白屏?
先在输出面板看宿主是否已启动;外壳模式下运行 VisualAppBuilder.exe --smoke 30 会写 shell-smoke.log,里面记录了首页是否渲染。白屏 99% 是宿主没起来 / 端口没握手上,不是前端。
装了插件但组件库里没有它?
打开「帮助 → 插件…」看两处:① 这个插件的「贡献组件」列了什么类型;② 有没有出现在「加载失败」里。加载成功且没贡献任何组件,说明它可能是生成器 / 主题插件,不是组件插件。
插件申请了读写文件 / 联网,能用吗?
默认不能。危险能力是默认拒绝:在「帮助 → 插件…」里给那个能力点「授权」,重启后生效。
一个插件把软件搞坏了,怎么关掉?
「帮助 → 插件…」→ 那个插件点「禁用」→ 重启。不需要删文件;被禁用的插件会单独列在「被禁用而跳过」里。
改了组件但导出没变?
导出前先保存(Ctrl+S);导出读的是当前 Schema。
误删了元素 / 页面?
Ctrl+Z。页面只剩一页时不允许删(会提示)。
隐藏了的元素,导出后还在吗?
不在。隐藏节点连同整棵子树都不会进导出工程。想临时收起画布又保留节点,用隐藏;想彻底不要,用删除。
能不能改后端语言 / 换成 C++?
不需要:瓶颈在启动与交互,不在 Kotlin 本身。路线是 AppCDS / 启动调优 → 懒加载 → 交互细节。
源码在哪、怎么自己打一个包?
gradlew :app:packageShell → 产物在 app/build/shell-image/VisualAppBuilder/。
第十六章 出问题时如何取证
| 需要什么 | 怎么做 |
|---|---|
| 宿主日志 | 输出面板;或 logs/host-*.log |
| 外壳冒烟 | VisualAppBuilder.exe --smoke 30 → shell-smoke.log |
| 前端错误 | 开发模式按 F12 打开 DevTools(外壳已开启 F12) |
| 打包体积 / 文件清单 | gradlew :app:packageShell 后看 app/build/shell-image/VisualAppBuilder/ |
| 报告问题时请带上 | 复现步骤 + shell-smoke.log 或 logs/host-*.log + 截图 |
想亲手验证本手册里的每条声明(跑测试、构建、行为验证),可参考仓库里的 docs/29_验收手册.md,里面把全部命令按「四层验证链」整理成可复现步骤。
附录 A 架构与实现要点
A.1 模块划分
| 模块 | 职责 | 依赖方向 |
|---|---|---|
| core | Schema 模型、组件元数据、校验、迁移、存储、布局语义 | 不依赖任何业务模块 |
| editor | 纯函数编辑内核(SchemaEditor / EditorState) | → core |
| preview | Schema → 近似渲染 | → core |
| generator | Schema → 平台无关 AST → Dart 源码 | → core |
| exporter | Dart 源码 → 磁盘 Flutter 工程(双模保护) | → core |
| plugin | 插件发现 / 隔离加载 / 能力白名单 / 契约校验 | → core |
| runtime | 多语言代码执行运行时 | → core |
| ide | 代码编辑器内核 + 图形化 IDE 状态中枢 | → core / editor / runtime |
| host | 本地 HTTP 服务 + SSE + 原生对话框 + 终端 / 调试 | → ide |
| app | 装配(唯一允许依赖全部模块) | → 全部 |
A.2 三条架构红线
- 布局三方同源:
core/layout/Layout.kt、generator/AstBuilder.kt、frontend/src/canvas/layout.ts三处的布局语义必须逐字一致,否则「画布所见 ≠ 导出所得」且不报错。 - 写 Schema 必持 commandLock:
EditorState.current只是引用快照,读-算-写无锁会丢节点 / 重复 id。 - 组件元数据住 core:属性面板由
ComponentDefinition自动生成,禁止手写。
A.3 前后端契约
- 22 个 REST 端点 + 7 类 SSE 事件(schema / code / selection / diagnostics / export / output / toast / debuglog)。
- 21 种 SchemaCommand,判别式字段名为
cmd,自有字段一律wire前缀。 - 统一响应包装
{ ok, data, error };HTTP 状态码语义化。 - 乐观并发:每个写请求带
baseRevision,冲突时前端自动重新拉全量 Schema 再重发一次。 - 令牌鉴权:所有
/api/*要求X-VAB-Token;SSE 因 EventSource 不能带自定义头,额外接受?t=(仅 SSE 允许)。
A.4 安全模型
- 宿主只监听 127.0.0.1,不暴露到局域网;会话令牌每次启动随机生成,常量时间比较。
- 终端 / 调试命令:白名单 op + 参数逐个校验 + 不经 shell + 可执行文件由宿主探测 + 工作目录由宿主决定。
- 资源复制:源与目标两侧都做路径穿越校验。
- 插件:每插件独立 URLClassLoader + 静态检查 + 危险能力默认拒绝 + 逐插件独立句柄。
附录 B 验证体系与质量数据
B.1 四层验证链
| 层 | 手段 | 保证什么 |
|---|---|---|
| ① 单元断言 | Kotlin 全模块 JUnit + 前端 vitest | 行为正确、边界覆盖、接线真的接上 |
| ② 金标准哈希 | 未接线工程整包 SHA-256 逐字节比对 | 新能力一律增量注入,不污染干净产物 |
| ③ 真实工具链 | dart analyze(类型 / 语义) | 生成的 Dart 是合法的(历史上抓到过 2 个编译级 bug) |
| ④ 行为验证 | flutter test(真实 Flutter 引擎) | 点了真的跳、数据真的流、焦点真的给 |
B.2 实测基线(2026-10-13)
| 项 | 数值 |
|---|---|
| 后端测试 | 10 模块 934 条(933 通过 / 0 失败 / 1 跳过) |
| 前端测试 | 837 条(72 个文件,0 失败) |
| E2E(真进程 + 真 HTTP) | 35 条,0 失败 |
| 真机端到端(模拟器 + adb) | 点击跳转已验证:点前只有「去设置」,点后只有「这是设置页」 |
| flutter test 行为验证 | 6 / 6 通过 |
| 宿主就绪时间 | 411–550 ms(AppCDS 生效) |
| 首屏体积 | 约 359 KB(Monaco 懒加载后,-89%) |
| 交付目录体积 | 129 MB |
| 离线验收 | 静态审计 0 外链 + 运行期零外部连接(仅监听 127.0.0.1) |
B.3 2026-10-13 审查后的加固项
本轮代码审查发现并修复了以下问题,每条都带回归护栏:
| # | 问题 | 修法 | 护栏 |
|---|---|---|---|
| 1 | 测试会污染用户真实 ~/.vab/preferences.json(两次事故,天生对断言免疫) | 新增 JUnit 全局扩展 PreferencesIsolationExtension,隔离从「记得写」变成「默认就有」 | 注册文件存在性 + 扩展真的生效 + 写入落点三重断言 |
| 2 | 状态栏红色错误文本不可点击(PRD 要求「红色且可点击查看原因」) | 挂 onClick={onShowError},标题说明点击后果,加 pointer 光标 | 新增点击用例 + 无错误时的反向护栏 |
| 3 | XxxPanel.tsx 与 xxx.ts 同名会在 Windows 上互相覆盖,无自动门禁 | 新增大小写折叠扫描测试 | 故意造冲突对验证逻辑非空转 |
| 4 | ServiceLoader 注册文件带 # 注释会导致 ServiceConfigurationError | 改为纯类名(Java ServiceLoader 不支持注释) | 断言无 # 且每行都是合法类名 |
| 5 | lock.ts 注释仍写「隐藏在阶段 1 无 UI 入口」(已过期) | 改为三处真实入口说明 | — |
B.4 已知限制(如实说明)
- 生成物能否在本机 flutter run 尚未端到端验证(本机 flutter create 会崩溃);已过 Dart 语法 / 类型 / 行为三道门禁。
- 第三方插件只验证过一个示例插件;多插件互相干扰未压测。
- 未出 WiX (msi) 安装包;当前为免安装目录版。
- 未签名 EXE 在他人机器上首次运行可能被 SmartScreen 拦截(根治靠代码签名)。
- Flutter 3.44 弃用了 Radio.groupValue/onChanged,产物有 2 条 info 级弃用提示(不阻断编译)。
- Kotlin 侧本轮加固尚未在本机跑 Gradle 全量回归(沙箱内 Gradle 原生库加载失败);已做括号平衡、import 匹配、反向护栏三重静态校验。
附录 C 名词对照表
| 名词 | 含义 |
|---|---|
| Schema | 项目的唯一真相源:一棵描述全部页面、组件、属性、主题、资源、导航的 JSON 树 |
| 元素 / 组件 | 画布上的一个可选中对象(按钮、文本、容器…) |
| 页面 | 一屏界面;导出后是一个 Dart 文件 + 一条路由 |
| 接线 | 元素和元素 / 页面之间的逻辑关系(跳转、数据流、事件触发) |
| 产物 / 导出工程 | 点「导出 Flutter 工程」后生成的标准 Flutter 工程 |
| revision | Schema 修订号,每次变更 +1;前端用它做乐观并发 |
| 连接器 | 画布右下角的接线图面板,接线的唯一编辑入口 |
| 自由定位 / 流式布局 | 顶层元素带坐标随意摆放 / 按 Column/Row 顺序排列 |
| itemTargets | 导航组件(底部导航 / 侧边栏 / 页签)的逐项跳转目标表 |
| focusedNode | 元素级跳转的路由参数,让目标页滚动并聚焦到指定元素 |
| 双模保护 | 生成文件被手改过就保留、不覆盖;lib/widgets/ 永不写入 |
| AppCDS | JVM 类数据共享归档:构建时 dump 热点类,运行时直接映射,省启动时间 |
—— 全文完 —
咔搭KaDa(Visual App Builder)V1.0 · 版权归属:飞翔的死猪 · © 2026 · 保留所有权利