| 名称 | ai2-app metadata: |
| 版本 | “1.1.0” |
| 描述 | 用 AI 生成 App Inventor 2 中文网(https://www.fun123.cn)应用——界面 + 代码块逻辑。根据需求生成完整 .aia、界面、代码块和素材;同一工程可编译安卓 Android 与鸿蒙 HarmonyOS 应用,苹果 iOS 即将支持。组件、属性、事件和积木逐项校验后才产出,杜绝导入后一片红块。已有工程可走平台 AI 助手。用户说"做一个 xx App"“帮我加一个 xx 功能”"生成界面/代码块"时用本技能。 |
ai2-app · 用 AI 做 App Inventor 应用
当前版本:1.1.0(见 VERSION);版本变化见 更新记录。
把用户需求落实为完整工程和可复核的验证证据。新建 App 或明确要求最终 .aia 时,使用本地生成通道,做到交付文件,不停在提示词、骨架或待用户补写的逻辑。
按用户目标选择通道:
| 通道 | 适合 | 产出 |
|---|---|---|
| ① 平台自带 AI 助手 | 修改平台上的已有工程 | 一条提示词 → 助手直接改工程 |
| ② 本地生成(本目录的 CLI) | 要交付 .aia 文件(老师备课、离线、批量) | out/<项目>.aia + 验证报告 + 预览页 |
| ③ 纯聊天提示词 | 用户只在网页版聊天 AI 里(跑不了脚本) | ai2-blocks 源码,贴给助手或预览页 |
按用途交付(先判断用户要的是什么)
不是每个请求都要产出工程。先看用户的用途,再定交付物:
| 用户怎么说 | 用途 | 交付 |
|---|---|---|
| 做个 App / 照截图做 / 这是题目要求 | 成品 | 通道②完整 .aia(下文主流程) |
| 先别生成 / 用哪个组件 / 怎么实现 / 给个方案 | 方案 | 不建 .aia,按下面「方案模式」交付 |
| 写教程 / 写文章 / 讲解怎么做 | 教程 | 按下面「教程模式」交付,文末附完整 .aia |
| 备课 / 教学案例 / 实验指导 / 每个组件一个案例 | 备课 | 每个案例一个 .aia + acceptance.md;组件全覆盖时按 references/delivery-validation.md「组件完整案例」 |
方案模式(只出方案,不生成工程):
- 需求拆解:要做的功能逐条列出,标出哪些依赖硬件、网络、权限或第三方服务。
- 组件选型表:组件中文名 + 文档链接 + 选它的理由 + 备选及取舍(如经典蓝牙/低功耗蓝牙、TinyDB/SQLite、多屏幕/单屏多面板)。
接口以
node $SKILL/lib/ai2gen.js components <关键词>查到的为准,易错点读references/component-tips.md。 - 数据设计:存什么、存在哪、格式样例(JSON/CSV/字节帧)。
- 关键积木思路:用 ```ai2-blocks 片段写出核心逻辑。片段也要能编译:把用到的组件放进一个临时工程跑一次
check,不过不给。 - 风险与边界:权限、后台运行、安卓与鸿蒙差异、需要用户自备的账号或硬件。
- 结尾一句:需要生成工程时说一声,按这个方案直接做。
教程模式(给读者照着做):
- 结构:最终效果 → 准备(组件清单表:中文名、作用、文档链接)→ 分步骤(每步写做什么、一段 ```ai2-blocks、运行后看到什么)→ 常见错误与排查 → 完整工程下载。
- 先把整个案例做成一个工程跑通
build,教程里的每段积木都从这个工程里截取,保证读者照抄能编译。 - 积木一律以块图呈现(预览页或在线预览页渲染),不贴 XML;组件写中文名并附文档链接(见下文写作规范)。
备课模式:
- 一个知识点一个案例,导入后打开就能演示;
acceptance.md写清导入后第一步、每个操作和预期现象,可直接当实验指导书。 - 批量出案例时共用一套命名、配色和界面规范,案例之间只换知识点。
- 学校只能用基础组件时加
--basic;能否导入 MIT 原版平台还取决于版本号,不要向用户承诺。
下文把本技能所在目录记作 $SKILL。通道②的命令都是 node $SKILL/lib/ai2gen.js …,
只需要 Node,不需要 App Inventor 源码或编译环境:build 对组件、属性、事件和每个积木逐项校验,通过才产出 .aia。
需求闭环与验收清单的要求见 $SKILL/references/delivery-validation.md,生成 .aia 前必读。不要去本机查找 appinventor 仓库——真实导入/编译校验是平台内部可选项,用户交付不需要。
通道①:平台自带 AI 助手(修改已有工程)
编辑器顶部工具栏右侧的 ✨「AI 助手」按钮。它能直接改工程:加组件、搭代码块、 设属性、建屏幕、导入拓展、生成图标,自动查错修复,每轮快照可一键撤销—— 这些能力外面的 AI 都没有。
你的工作是把需求整理成一条好提示词让用户贴进去。具体写法、迭代说法、
关键问题与解决方案,读 $SKILL/references/assistant.md(每次走这条通道前都读)。
要点速记:
- 提示词结构:一句话定位 + 界面从上到下 + 每个交互干什么 + 数据存哪。
- 拿不准的 API 用自然语言描述意图,让助手自己查库选组件——它不猜。
只有十足把握才附 ```ai2-blocks 围栏(语法见
references/ai-blocks.md)。 - 改需求用增量说法(「把按钮改成绿色」),不要重发整个需求。
- 后续迭代、排错都引导用户在助手面板里完成,别拉回来重新生成。
- 界面截图 / 报错截图 / CSV 数据都能当附件发给它(截图需多模态模型)。
通道②:本地生成 .aia(CLI)
一个 App = 一个目录
myapp/
app.json 界面(组件树 + 属性)
Screen1.ai-blocks 这个屏幕的逻辑
assets/ 图片/音频等素材(可以没有)
out/ 构建产物(工具生成,别手写)
常用命令:
node $SKILL/lib/ai2gen.js new myapp # 起最小骨架,按需求补全
node $SKILL/lib/ai2gen.js --version # 查询当前技能版本
node $SKILL/lib/ai2gen.js check myapp # 源文件预检(写完先跑)
node $SKILL/lib/ai2gen.js build myapp # 生成 .aia(逐项校验通过才产出)+ 预览页
node $SKILL/lib/ai2gen.js preview myapp # 只重新生成预览页(不动已验证的 .aia)
node $SKILL/lib/ai2gen.js serve myapp # 起本地服务器看预览(离线可用)
node $SKILL/lib/ai2gen.js components Button # 查组件到底有哪些属性/事件/方法
校验库由当前仓库的内置组件与本平台拓展构建(数量以 components --list 为准),拓展的属性/事件/方法一样会被逐字核对。别人的第三方拓展用 --ext 喂进来:
node $SKILL/lib/ai2gen.js check myapp --ext ~/Downloads/com.acme.Foo.aix # 也可以给一个目录
.aix 的真实描述符用于校验;构建时将实际类文件和资源一起嵌入 .aia。本平台拓展(DeepSeek、ECharts、MLKit 等)不用手动准备:构建时自动从文档站下载对应 .aix,缓存在技能目录 .cache/aix/,需要联网。第三方拓展只知道组件名而没有实际拓展包时,构建会失败。--ext 要同时用于 check/build/verify。
美化需求(渐变背景、圆角、卡片、阴影、边框)直接用内置「组件美化」ComponentEnhance
(SetBgColor(组件, 颜色表, 方向) 就能做多色渐变,另有 SetAsCard / SetRoundCorner /
SetElevation / SetBorder),不要引入 KIO4_* 之类第三方美化拓展——功能重复,用户还得额外装包。
标准流程
- 听懂需求。用户要什么功能、有哪些按钮、点了之后发生什么。 只在真的会做出两种完全不同的东西时才追问一句,否则按最常见的理解直接做。
- 起骨架:
new myapp(目录名用英文,会成为默认项目名)。 - 写界面
app.json。动手前读$SKILL/references/components-common.md和 界面与交互设计,先按业务选择页面结构,再查组件实现。 用到的组件先查 组件用法要点:每个组件最容易用错的地方(与平台 AI 助手同一份),如布局里谁设“充满”、标记必须放进地图、云数据库读取是异步事件等。 (常用 + 中文版增强组件的完整属性/事件/方法;独有组件全表在references/components-cn.md)。 冷门组件用components命令查,别猜。 - 写逻辑
Screen1.ai-blocks。语法读$SKILL/references/ai-blocks.md, 可用的内建函数读$SKILL/references/builtins.md。 check到零错误。报错都带「你是不是想写 X」,照着改,别绕过。- 完成需求闭环:所有按钮、事件、数据保存/恢复、错误/空数据处理有实际逻辑;资源完整,界面名称与代码一致。按
$SKILL/references/delivery-validation.md逐项验收,并对照product-design.md检查订单详情、异步等待/超时、筛选后选中状态等操作细节。 build到零错误:最终归档里的每个组件、属性、事件、积木和全局变量都按元数据逐项核对,有错误不产出。 平台内部有源码环境时可加--repo <appinventor目录>追加真实导入与编译校验;用户交付不需要,也不要为此去找仓库。- 交付:按用户选择给最终 .aia及必要使用说明。用户说“.aia源码”时指可导入、可编辑的
.aia工程;只要最终.aia时不另发JSON、脚本、预览或报告。验证记录仍内部保存,预览只作辅助。
app.json 速览
完整规则见 $SKILL/references/ui-spec.md。
{
"name": "GuessNumber",
"appName": "猜数字",
"screens": [{
"name": "Screen1",
"title": "猜数字",
"properties": { "AlignHorizontal": "3", "BackgroundColor": "&HFFF5F5F5" },
"components": [
{ "type": "Label", "name": "标签_提示", "text": "我想了一个 1-100 的数",
"properties": { "FontSize": "18" } },
{ "type": "HorizontalArrangement", "name": "排列_输入",
"properties": { "Width": "Fill parent", "AlignVertical": "2" },
"children": [
{ "type": "TextBox", "name": "输入框_猜测",
"properties": { "Hint": "输入数字", "NumbersOnly": "True", "Width": "Fill parent" } },
{ "type": "Button", "name": "按钮_猜", "text": "猜" }
] },
{ "type": "Notifier", "name": "对话框1" }
]
}]
}
要点:
name是项目名,必须英文字母开头、只含字母数字下划线;中文名写在appName。- 组件名建议
类型_用途(按钮_提交、标签_状态),比Button1好读,逻辑里也好认。 text是properties.Text的简写,title是屏幕properties.Title的简写。- 尺寸写
"Fill parent"、"Automatic"、"50%"或像素数字;颜色写"&HFFRRGGBB"或"#RRGGBB"或red这类颜色名 —— 工具会归一化。 - 排列(Arrangement)和布局列表框(LayoutListView)可以有
children;列表框的直接子布局是行模板。 - 非可视组件(Notifier / TinyDB / Clock / Web …)直接放在
components顶层。
ai2-blocks 速览
多行文本块
需要带换行的长文本时,字符串必须一行写完,换行用 转义——含换行的字符串会自动生成
「多行文本」块(text_multiline_text),单行字符串仍是普通文本块。不要把多行内容拆成多个
普通文本块再 join;也不要在字符串里写真实换行(词法层按行读,未闭合的字符串直接报错)。
global 日志 = "开机自检完成
等待指令"
when 按钮1.Click() {
日志 = join(日志, "
点击了按钮")
标签1.Text = 日志
}
AI 助手读写两侧对称:写—— 转义自动升级为多行文本块;读——反编译现有工程时,
多行文本块也以 转义显示,round-trip 类型不变。在线代码块预览同样支持,
修改切片来源(AiBlocksCompiler/IntentConverter)后需重建 appengine/tools/block-preview
预览包,不能只更新未压缩中间文件。
完整语法见 $SKILL/references/ai-blocks.md,内建函数见 builtins.md。
global 目标 = 0
global 次数 = 0
when Screen1.Initialize() {
目标 = random(1, 100)
}
when 按钮_猜.Click() {
var 猜 = 输入框_猜测.Text
次数 = 次数 + 1
if 猜 > 目标 {
标签_提示.Text = "小一点"
} else if 猜 < 目标 {
标签_提示.Text = "大一点"
} else {
对话框1.ShowAlert(join("猜对了!用了 ", 次数, " 次"))
}
}
要点:
- 只有三种顶层结构:
global 变量 = 初值、when 组件.事件(参数){}、procedure 名(参数){}/function 名(参数){ … return 值 }。语句不能裸露在顶层。 - 用到的全局变量必须先
global声明;局部变量用var,直接平铺写,嵌套由编译器处理。 - 列表下标从 1 开始:
词表[1]。 - 条件里
=和==都当相等比较。 - 改已有逻辑用
replace when 组件.事件(){…}—— 同名事件整体替换;不加replace是追加。
已有项目加功能(粘贴通道)
用户已经有工程、只想加个功能时,不要让他导入 .aia(会变成另一个新项目)—— 这种场景优先走通道①(助手直接在工程里改)。用户不想用 AI 助手时才走粘贴:
- 让用户先告诉你他工程里已有哪些组件(截图或直接说)。app.json 里把这些组件照抄一份 (名字、类型对上即可,属性可以省),这样校验才能验到真实组件。
Screen1.ai-blocks里只写新增或要替换的事件。build之后把out/Screen1.paste.xml的内容给用户,让他: 打开代码块编辑器 → 点空白处 → Ctrl+V。块会直接出现,可以拖到合适位置。- 界面上要加的组件,告诉用户在设计器里怎么拖、属性设成什么(工具的界面产物这时用不上)。
仿照大学排名案例生成实际应用
生成可用案例前,先读 references/delivery-validation.md 的「大学排名案例经验」。以实际业务流程组织界面与积木;覆盖全部API时,把高级设置和异常检查放在独立面板,默认界面保留常用操作。不要生成逐个调用方法的按钮集合来代替应用。
组件完整功能案例
用户要求每个组件一个 .aia、涵盖全部功能时,先读 references/delivery-validation.md 的「组件完整案例」部分。按当前元数据逐项实现属性、方法和事件,用最终 .aia 执行 API 覆盖检查;禁用或无法由事件到达的过程不算覆盖。硬件、账号及平台条件写入工程说明,不能用空处理器或假结果代替。普通应用不要求覆盖其中每个辅助组件的全部 API。
交付说明
build 成功(verification.json 的 status 为 checked,SHA-256 与当前 .aia 一致)即可交付 .aia。交付最终 .aia 及必要配置;用户只要最终 .aia 时,报告内部留存,不在下载入口列出中间文件。
成品在 App Inventor 2 中文网(https://www.fun123.cn)打开、调试、编译,交付时把这三步告诉用户:
登录 fun123.cn 导入 .aia → 用 AI 伴侣扫码在真机上调试 → 编译安卓 APK 或鸿蒙 HAP。
工程用到中文网独有组件(速查表里的 ▲,如导航条、SQLite、低功耗蓝牙)时,要说明这些组件只在 fun123.cn 提供,
MIT 原版平台打不开该工程。编译 App 需要开通 VIP:https://www.fun123.cn/reference/info/vip.html?f=skill。
导入:App Inventor →「项目」→「导入项目(.aia)」→ 选择文件。项目重名时改用新项目名,不建议删除用户已有工程。说明完成了哪些功能;AI 伴侣和真机未实测时明确写“尚未验证”。
说明里如实写清验证范围:组件与积木已逐项校验;导入后在平台上编译、AI 伴侣和真机运行由用户完成,没实测的不写“已跑通”。
预览页记得让用户看一眼:联网时直接打开 out/preview.html 即可;离线用 serve 后打开
http://127.0.0.1:8123/。左边是界面示意图,右边是预览工具绘制的真实代码块图,块图上有「复制代码块」按钮。
给用户看的预览只能是工具生成的 out/preview.html(或把它发布出去),不要自己另写 HTML。
通道③:纯聊天版提示词
用户只能吐文本、跑不了脚本(网页版 ChatGPT / DeepSeek 之类)时,用
$SKILL/PROMPT.md —— 一段可以整段粘进对话的单文件提示词,产出 ai2-blocks 源码。
能力弱一档,但不需要装任何东西。
在线预览页(已上线,无需安装):https://www.fun123.cn/static/ai2-preview/
把 ai2-blocks 源码贴进去就渲染成块图,块图右上角的「复制代码块」复制的是标准块 XML,
到 App Inventor 的代码块编辑器里 Ctrl+V 就直接进工程 —— 不用照着拖。
工程里没有同名组件时组件块会标红,改成自己的组件名即可。
第三方拓展也能预览,但要提供它的 .aix:在线页内置的是 当前构建的内置组件与本平台拓展的
描述符。别人的拓展不在里面时,块照样画得出来也不报错,但事件参数会静默丢失
(when Foo1.OnResult(code, message) 变成没有参数的事件块,body 里引用参数的地方就断了)。
这种情况请改用通道② + --ext 那个.aix,或让平台方把 aix 收进预览库。
铁律
-
按交付目标选通道:新建 App 或要求 .aia 时直接生成完整工程并验证;修改平台已有工程可使用平台助手。用户明确要求的交付形式优先。
-
.aia 必须
build通过才交付(通道②):check只是预检;build对最终归档逐项校验,有错误不产出,不能手改或拼接 .aia 绕过。 -
组件的属性名、事件名、方法名一律不许猜。通道②用
components命令 3 秒查到准确的; 通道①让助手自己查。猜错的代价是用户导入后一片红块,而他不会修。这不是假设——我们审计过自家 344 段文档伪代码,286 条 API 是错的,全是"看着很合理"的猜测:
猜出来的 真相 Canvas.DrawRect(left, top, right, bottom)Canvas 根本没有画矩形的方法,只能 DrawShape或四条DrawLineCanvas.DrawText(x, y, "字", 颜色)真签名 DrawText(text, x, y),文字在前,颜色是画布的PaintColor属性Web1.GotText(网址, 响应码, …)事件参数名是固定的英文内部名 url, responseCode, responseType, responseContent按钮1.Click(某参数)Click没有参数,多写的会变成没赋值的变量Player1.Loop()Loop是属性不是方法:播放器1.Loop = trueNotifier1.ShowAlert("标题", "内容")ShowAlert只有 1 个参数;两个参数的是ShowMessageDialog(message, title, buttonText)图像精灵1.X坐标成员名一律英文内部名 X;中文只是块上的显示图像精灵1.EdgeReached()真签名 EdgeReached(edge),反弹用Bounce(edge)规律:猜错的从来不是"没听过的 API",而是"听起来天经地义的 API"。所以规矩很简单—— 写下任何
组件.成员之前,它要么刚从components命令的输出里看到过,要么就去查, 要么改成自然语言让平台 AI 助手来选。 -
专门组件优先,别用积木硬模拟。底部/顶部导航用
Navigator导航条(别拿一排按钮模拟)、 侧边抽屉与底部弹出面板用PopupPanel、底部提示用Snackbar、下拉刷新用SwipeRefresh、 设置页用SettingsList、星级评分用RatingBar、图片轮播用ImageCarousel、圆角卡片/渐变用ComponentEnhance——专门组件本身就是最简单的实现,默认放心用。完整对照表见references/product-design.md,全部独有组件见references/components-cn.md。 用到独有组件时,交付说明里提示用户:工程需在 fun123.cn 打开,编译需开通 VIP(见「交付说明」)。 用户声明「只用基础组件 / 不用中文版独有组件 / 要能导入 MIT 原版」时才退回基础组件做法 (此时按钮+排列模拟是正当的)——独有组件的标识是编辑器调色板橙点 / 速查表里的▲, check/build/verify 加--basic会强制拦截。 -
事件参数逐字照抄签名。
when Web1.GotText(url, responseCode, responseType, responseContent)—— 少一个、改一个名字,块里读到的就是未定义变量。check会拦,但别指望它。 -
组件实例名用中文,成员名用英文:
标签_状态.Text、when 按钮_提交.Click()。 中文实例名和用户在设计器里看到的一致;成员名是 App Inventor 的内部名,必须英文。 -
涉及原生组件的说明、组件清单或教程文字要用中文组件名并附组件文档链接:例如
[照相机](https://www.fun123.cn/reference/components/media.html#Camera)、[拍摄完成](https://www.fun123.cn/reference/components/media.html#Camera.AfterPicture)。 代码块内不能嵌 Markdown 链接,组件实例名仍写中文、成员名仍写英文;拓展组件保留其真实名称。 -
拍照识图要直传本地路径:
when 照相机1.AfterPicture(image)的image参数就是拍摄后的本地图片路径; 目标方法是ChatWithImage(prompt, imagePath)时直接传入image,不要改成ChatWithImageUrl或先拼网络地址。 -
屏幕名是唯一例外:默认屏幕必须叫
Screen1(多屏继续用Screen2、Screen3),不能写成屏幕1;屏幕事件使用when Screen1.Initialize()等英文内部名。 -
有返回值的方法不能当独立语句。
本地数据库1.GetValue(...)要赋给变量或当参数用。 -
不许手写
.scm/.bky/ Blockly XML。这些是工具的产物;手写必错,而且没人能审。 -
代码块一律用预览工具画成块图,不许把 XML 当文本展示。预览页用
ai2gen build/preview生成的out/preview.html(块图由预览工具渲染,用到的组件数据已内嵌,单独打开也能画出); 不要自己拼 HTML 把 Blockly XML 放进<pre>、表格或文本框——用户只会看到一堆无规则的 XML。 确需自建页面时,块必须放进<div data-ai2-blocks>…</div>并引入https://www.fun123.cn/static/ai2-preview/ai2-block-preview-loader.min.js(data-base指向同目录), 交付前打开页面确认显示的是块图。 -
一次只改该改的。给已有项目加功能时,只写新增/修改的那几个事件, 用
replace when覆盖旧逻辑,不要把整个工程重发一遍。
能力边界(别硬撑,如实告诉用户)
- 多屏跳转:通道①可以让助手建多屏(
加一个 Screen2 做登录页);通道②的 ai2-blocks 写不出屏幕跳转块,多屏项目只能导入后手工加。两条通道都优先推荐单屏多面板: 每个"页面"是一个VerticalArrangement,切页面就是改各面板的Visible; 多页面 App 的底部导航用导航条Navigator(写法见recipes.md), 只有用户要求只用基础组件时才退回一排按钮切换(--basic)。 - 别人的第三方拓展,没有
.aix就校验不了。让用户把.aix发给你(他既然要用,手上一定有),--ext喂进来就能精确校验。实在拿不到,不要硬写 —— 明说"这个拓展的块我没法核对, 你把 .aix 发我,或者照它的文档自己拖",比编一套跑不通的块有用。build --ext会把真实拓展二进制与资源打包进 .aia,缺少实际文件时禁止构建。 - 界面预览是 HTML 近似图,字体、系统控件外观和真机有差;布局对不对能看出来, 像素级还原不要指望。
- 素材必须落实。CLI 不生成图片,但执行技能的 AI 应按需求使用可用图片生成工具、仓库素材或合适的代码绘图创建资源,放入
assets/后引用。缺少用户专属素材时再询问,不用空文件冒充。
平台内部为文档站生成案例 .aia 时,按仓库 AGENTS.md 加 --repo 走完整校验(正式编辑器载入、真实导入、编译),文档下载链接带最终文件 SHA-256 版本参数;普通用户交付不需要这一步。