通用 - 定义 Block¶
核心结构¶
在扩展文件目录的 index.js 文件中通过 getInfo() 方法返回配置对象,必须包含以下结构:
getInfo() {
return {
name: '扩展名称',
menuIconURI: '扩展菜单图标',
blockIconURI: '扩展积木块图标',
color1: '#颜色值',
color2: '#颜色值',
color3: '#颜色值',
blocks: [ /* 积木定义列表 */ ],
menus: { /* 下拉菜单配置 */ }
};
}
积木定义(blocks 数组)¶
每个积木对象需配置以下属性:
1. opcode¶
- 作用:积木唯一标识符,与代码生成逻辑关联
- 格式:字符串
- 示例:
opcode: 'arduino_set_pinMode'
2. blockType¶
- 类型:
BlockType枚举值 - 可选值:
| 类型 | 形状 | 用途 |
|---|---|---|
HAT | 帽子形 | 事件触发器 |
COMMAND | 方形 | 执行命令(无返回值) |
REPORTER | 圆形 | 返回数据(如传感器读数) |
BOOLEAN | 菱形 | 返回布尔值 |
3. text¶
- 作用:定义积木显示文本
- 多语言支持:建议使用
formatMessage - 语法:
- 参数占位符:
[ARG]对应arguments中的字段
4. group¶
- 作用:积木所属功能分组
- 多语言示例:
5. arguments¶
- 作用:定义输入字段(如数字输入框、下拉菜单)
- 结构:
- 常用 field 类型:
| 常用类型 | 说明 |
|---|---|
STRING | 字符串输入 |
NUMBER | 数字输入 |
SLIDER | 滑动条(需配置 rangeMin/rangeMax) |
💡 field 用法详细介绍:通用-Field类型总览
下拉菜单(menus 对象)¶
1. 简单菜单¶
2. 复杂菜单¶
menus: {
dynamicMenu: {
acceptReporters: true, // 是否允许拖入积木
items: [
{ text: '自定义文本', value: 'CUSTOM' }
]
}
}
3. 动态菜单¶
可通过类方法动态生成:
_initPinMenu() {
return [ {
text: {id: '翻译ID', default: '数字引脚2' },
value: 'D2',
} ];
}
menus: {
pinMenu: this._initPinMenu()
}
注意事项¶
- 参数占位符格式必须为
[ARG],且与arguments中的字段名一致 - 滑动条类型必须配置
inputParams.rangeMin/Max - 多语言 ID 需与翻译文件中的键名严格对应
模板示例¶
1. 基础下拉框¶
{
opcode: 'select_serial_port',
text: '选择串口 [PORT]',
blockType: BlockType.COMMAND,
arguments: {
PORT: {
type: ArgumentType.STRING,
menu: 'serialPortMenu', // 对应 menus.serialPortMenu
defaultValue: 'UART1'
}
}
}
2. 带校验的输入框¶
{
opcode: 'set_wifi_password',
text: '设置密码: [PWD]',
blockType: BlockType.COMMAND,
arguments: {
PWD: {
type: ArgumentType.STRING,
inputParams: {
validate: '_validatePassword' // 校验函数
},
defaultValue: '12345678'
}
}
}
3. 数值范围滑块¶
{
opcode: 'set_motor_speed',
text: '电机速度 [SPEED]%',
blockType: BlockType.COMMAND,
arguments: {
SPEED: {
type: ArgumentType.NUMBER,
inputParams: {
rangeMin: 0,
rangeMax: 100
},
defaultValue: 50
}
}
}
特殊用法¶
1. 下拉框联动机制¶
定义:根据下拉框 A 的不同选择,下拉框 B 随之展示不同内容。
案例分析: * 场景:当硬串口1/硬串口2切换时,刷新 Rx 的引脚默认值显示和下拉菜单。 * 实现思路: 1. 监听串口切换:记录当前 block 的 id 及串口数据。 2. 监听 Rx 下拉框点击:判断当前的硬串口值,返回不同的下拉菜单列表。
关键点:需要理解 BlockID 的管理机制。Workspace 中每个 block 有唯一的 id。
代码实现:
-
定义积木 (blocks):
blocks: [ { opcode: 'pico_serialRemapping', text: '选择 [SERIALPORT] Rx [PINR]', blockType: BlockType.COMMAND, arguments: { SERIALPORT: { type: ArgumentType.STRING, menu: 'serialTypeMenu', defaultValue: this.getCurrentSerialDefault(true), }, PINR: { type: ArgumentType.STRING, menu: 'pinRMenu', defaultValue: 'GP1', } } } ], menus: { serialTypeMenu: this._getSerialTypeMenu(), pinRMenu: this._getPINRMenu(), } -
串口切换监听 (Func):
// block串口数据对象 this.serialType = {}; // 重置Flyout区block状态 setDefaultSerial(defaultSerial) { let regex = /.*_serialRemapping$/; // block的opcode Object.keys(this.serialType).map(_item => { if (regex.test(_item)) { this.serialType[_item] = defaultSerial; } }) } // 获取/重置串口的默认value getCurrentSerialDefault(isReset) { if (isReset) this.setDefaultSerial('Hardware Serial1'); return 'Hardware Serial1'; } // 监听串口的切换 _getSerialTypeMenu() { const self = this; return { items: function () { // block创建时, this.sourceBlock_ = null if (this.sourceBlock_) { // 设置初始串口值 if (!self.serialType.hasOwnProperty(this.sourceBlock_.id)) { let defaultSerial = self.getCurrentSerialDefault(false); self.serialType[this.sourceBlock_.id] = defaultSerial; } // 当串口切换时 if (this.value_ !== self.serialType[this.sourceBlock_.id]) { // 更新串口对象serialType self.serialType[this.sourceBlock_.id] = this.value_; // 更新联动的下拉框的默认值 if (self.serialType[this.sourceBlock_.id] === "Hardware Serial1") { // setFieldValue: 参数1:默认值; 参数2:text中的对应参数 this.sourceBlock_.setFieldValue("GP1", "PINR") } else { this.sourceBlock_.setFieldValue('GP9', 'PINR') } } } // 返回下拉框列表 return [ ["硬串口1", "Hardware Serial1"], // [显示文本, 实际value] ["硬串口2", "Hardware Serial2"] ] } } }💚 提示: 1.
setFieldValue方法的第二个参数,必须和 block 对象中arguments参数中的属性名一致。 2._getSerialTypeMenu方法返回的串口下拉框列表中,默认值必须排第一个。 -
下拉框联动控制 (Rx 菜单):
// 监听 Rx 的下拉框点击 _getPINRMenu() { const self = this; return { items: function () { if (!this.sourceBlock_) return [['1', '1']]; // 设置初始串口值 if (!self.serialType.hasOwnProperty(this.sourceBlock_.id)) { let defaultSerial = self.getCurrentSerialDefault(false); self.serialType[this.sourceBlock_.id] = defaultSerial; } // 根据串口值返回不同的下拉框列表 if (self.serialType[this.sourceBlock_.id] === "Hardware Serial1") { return [["GP1", "GP1"]]; } else { return [["GP9", "GP9"]]; } } } }
2. 输入校验规范¶
类型限制【仅上传模式支持】 * inputTypes: 指定拖入积木的返回类型【带输入框的积木】 * outputTypes: 指定积木的返回类型【圆形与菱形积木】
{
opcode: 'getTarget',
blockType: BlockType.REPORTER,
text: '获取 [TARGET]',
arguments: {
TARGET: {
inputTypes: [...DataType.NUMBER] // 允许数字类型输入
}
},
outputTypes: [DataType.STRING] // 定义积木输出类型
}
DataType 可选参数数据类型:
| 字符串值 | 说明 |
|---|---|
'int32_t' | 数字类型 |
'uint32_t' | 数字类型 |
'string' | 字符串类型 |
'float' | 浮点类型 |
'bool' | 布尔类型 |
'void' | 空类型 |
'void*' | 空指针类型 |
'color' | 颜色 |
'expression' | 表情 |
'preview' | 掌控的屏幕显示文字预览 |
'setting' | 所有的设置下拉框 |
注意:DataType.NUMBER 需要展开,写法如下: * inputTypes: [...DataType.NUMBER] * outputTypes: [...DataType.NUMBER]
积木 field 输入值正则校验:
arguments: {
ACCOUNT: {
type: ArgumentType.STRING,
defaultValue: 'yourSSID',
inputTypes: [DataType.STRING],
inputParams: { validate: this._validatePass },
}
},
// 校验函数定义在类中
_validatePass(text) {
var regx = /^[\x00-\x7e\u4e00-\u9fa5]{1,}$/;
if (text && !regx.test(text)) {
return null; // 校验失败
}
if (text === "") {
return "yourSSID"; // 空值恢复默认
}
return text; // 校验通过
}
3. 积木 field 符号显示¶
symbol: 指定积木 field 显示特定符号,例如字符串输入框默认引号、列表默认中括号
arguments: {
PATH: {
type: ArgumentType.STRING,
inputParams: {
symbol: '""' // 在输入框两端显示引号
},
defaultValue: "image.jpg"
}
},
4. 扩展二级菜单¶
submenuId: 指定定义的二级菜单 。
注意二级菜单文字(json翻译文件中)不能有特殊字符(引号、&、<、>等),否则会导致积木无法显示。
blocks: [
////////////////////////////// 定义二级菜单 ///////////////////////////////
{
blockType: BlockType.SUBMENU,
id: 'boardSensor',
text: formatMessage({
id: "deviceTemplate.submenu.boardSensor",
default: 'board\'s sensor'
}),
},
////////////////////////////// 主程序 ///////////////////////////////
{
opcode: 'sensorBlock',
blockType: BlockType.COMMAND,
text: formatMessage({
id: 'deviceTemplate.sensorBlock',
default: 'This is a sensorBlock block',
}),
submenuId: "boardSensor", // 指定二级菜单
arguments: {
},
},
]