编写 API 2 桌宠
目标:用完整的本地模块实现一个状态球,不依赖外部图片、网络或构建步骤。下载可导入 ZIP,在设备交互的桌宠设置中导入。
打开
目录与清单
text
manifest.json
config.toml
scripts/main.jsjson
{
"apiVersion": 2,
"id": "lyra.docs.status-orb",
"name": "Status Orb",
"version": "1.0.0",
"author": "Lyra Code documentation",
"entry": "scripts/main.js",
"config": "config.toml",
"controls": [
{ "key": "color", "label": "Color / 颜色", "type": "color", "default": "#5b7cfa" }
]
}apiVersion、id、name、version、author 和 .js 入口必填。包内只应有一个清单;资源路径相对包根,不使用绝对路径或 ..。
toml
[pet]
size = 96
autoDock = true
soundEnabled = false
[controls]
color = "#5b7cfa"TOML 使用宿主支持的标量子集。自定义颜色通过清单 controls 声明,优先级为默认值 → 包配置 → 本机保存的个人参数。
模块生命周期
js
let orb;
let state = 'idle';
let color = '#5b7cfa';
const labels = {
idle: 'Ready', thinking: 'Thinking', executing: 'Working',
approval: 'Waiting', completed: 'Done', error: 'Error', paused: 'Paused'
};
function render() {
if (!orb) return;
orb.textContent = labels[state] || 'Ready';
orb.style.background = state === 'error' ? '#c23743' : color;
}
export default {
mount(api) {
orb = document.createElement('div');
orb.style.cssText = 'width:88%;height:88%;margin:6%;border-radius:50%;display:grid;place-items:center;color:white;font:600 13px system-ui;box-shadow:inset 0 -8px 16px #0002;user-select:none;';
api.root.append(orb);
color = api.config?.color || color;
render();
},
onEvent(type, data) {
if (type === 'state') state = data.state;
if (type === 'config') color = data.color || color;
if (type === 'tap') orb?.animate(
[{ transform: 'scale(1)' }, { transform: 'scale(.9)' }, { transform: 'scale(1)' }],
{ duration: 220 }
);
render();
},
unmount() {
orb?.getAnimations().forEach(animation => animation.cancel());
orb?.remove();
orb = undefined;
state = 'idle';
color = '#5b7cfa';
}
};mount 创建渲染节点,onEvent 处理 config、state 和 tap,unmount 取消动画并移除节点。宿主处理点击、长按和拖动;不要依赖脚本 DOM 点击来执行系统操作。
设备验收
- 导入 ZIP,应显示
Ready状态球,长按能进入设置。 - 修改颜色,球的颜色应更新;重新选择后个人参数仍按应用规则保存。
- 发起任务,状态随任务变化,例如 Thinking、Working、Waiting 或 Done。
- 点击应有短暂缩放反馈;切换到默认桌宠再切回,节点不应重复。
- 完成后按需移除示例;导入失败时保留错误与当前包,检查唯一清单、入口及语法。
脚本无法任意联网或执行 Shell。需要动画资源时,通过 api.asset() 或精灵接口加载包内文件,并在卸载时清理计时器与音频。更完整的协议见应用仓库 API 2 指南。
