# L2 · 设置表单 > 前置:[L0](./01-hello-plugin.md)。声明式 schema:插件声明「要什么配置」,宿主负责渲染、持久化、实时回推。不用写任何 UI 代码。 ## 1. 声明设置 ```js export default function definePlugin(api) { api.ui.registerSettings({ items: [ { type: 'string', key: 'apiKey', label: 'API Token', password: true, placeholder: 'sk-...' }, { type: 'boolean', key: 'verbose', label: '详细日志', default: false }, { type: 'select', key: 'endpoint', label: '接入点', default: 'prod', options: [ { value: 'prod', label: '生产' }, { value: 'staging', label: '预发' } ] }, { type: 'button', key: 'test', label: '测试连接', variant: 'primary' } ] }) } ``` 保存后(开关切换或重启): - 设置 → 插件 → **全局/项目** 作用域里,该插件行内出现 ⚙ 按钮(打开配置页)和「一级入口」开关 - **items 为空或不声明 → 两个控件都不出现**(这正是"留空则无一级入口按钮"的规则) ## 2. 一级入口 行内「一级入口」开关打开后,设置弹窗左侧导航「Agent 能力」组末尾出现以插件名命名的入口,点击进入该插件的独立配置页。用户随时可以关掉。 ## 3. 读写值 ```js const values = api.ui.getSettingValues() // { apiKey: '...', verbose: false, endpoint: 'prod' } // schema 里的 default 已合并——没被用户改过的键直接拿默认值 api.ui.onSettingsChange((next) => { // 用户在设置页改值后实时推送 values = next api.log.info('settings changed', { endpoint: next.endpoint }) }) api.ui.onSettingsAction((key) => { // button 条目点击(key = 按钮项 key) if (key === 'test') { const ok = values.apiKey ? '✅' : '❌ 缺少 API Token' api.ui.setStatusItem('test', { text: `连接测试 ${ok}`, tone: 'accent' }) } }) ``` 值持久化在 `userData/aso-plugin-values.json`(按插件隔离),重装插件后仍在。 ## 4. 13 种标准控件 | type | 说明 | 关键字段 | |---|---|---| | `string` | 单行输入 | `password` 掩码、`placeholder` | | `text` | 多行文本 | `rows` | | `number` | 数字 | `min` / `max` / `step` | | `boolean` | 开关 | — | | `select` | 下拉单选 | `options[{value,label}]` | | `multiSelect` | 多选(chip 组) | `options` | | `slider` | 滑条 | `min` / `max` 必填、`step` | | `color` | 颜色(#rrggbb) | — | | `path` | 文件/目录选择 | `mode: 'file' \| 'directory'` | | `image` | 图片选择 + 缩略图 | — | | `button` | 动作按钮 | `variant: 'primary' \| 'ghost'` | | `info` | 静态说明 | — | | `divider` | 分割线/小节标题 | `label?` | 全部条目支持 `label` / `description` / `default`(button/info/divider 除外)。 ## 5. 设计约束(为什么是数据不是代码) - schema 是**纯数据**:不允许函数/React 元素——宿主跨进程渲染并持久化快照 - 需要动态选项(比如扫描出来的设备列表)?在激活时计算好再 `registerSettings`,每次激活都会重新声明 - 需要复杂交互 UI?那不是设置的职责——走 [L4 React 组件](./05-renderer-components.md) ## 6. 验证 1. 重载插件 → 插件页该行出现 ⚙ 与「一级入口」 2. 打开配置页改一个值 → 日志出现 `settings changed`(`onSettingsChange` 生效) 3. 点按钮 → 状态胶囊出现(动作回调生效) 4. `userData/aso-plugin-values.json` 里能看到写入的键值 --- **上一篇** [L1](./02-tools-and-commands.md) · **下一篇**:[L3 UI 槽位](./04-ui-slots.md)——状态胶囊、面板、视图与 iframe 页。