> ## Documentation Index
> Fetch the complete documentation index at: https://docs.blinko.space/llms.txt
> Use this file to discover all available pages before exploring further.

# 插件设置面板

> 每个Blinko插件都可以拥有自己的设置面板，允许用户自定义插件行为。

# 插件设置面板

<img className="rounded-2xl" src="https://mintcdn.com/blinko/AgHVAkfwbrWVbQ0E/images/2025-02-20-17-39-08.png?fit=max&auto=format&n=AgHVAkfwbrWVbQ0E&q=85&s=c47e167aa516171a827f4dc537370e99" width="1658" height="252" data-path="images/2025-02-20-17-39-08.png" />

## 启用设置面板

在您的插件类中设置`withSettingPanel = true`来启用设置面板：

```typescript theme={null}
export class MyPlugin extends BasePlugin {
  // Enable settings panel
  withSettingPanel = true;

  // Render settings panel
  renderSettingPanel = () => {
    const container = document.createElement('div');
    render(<Setting />, container);
    return container;
  };
}
```

## 创建设置组件

创建一个独立的Preact组件来管理设置界面：

```typescript theme={null}
// src/setting.tsx
import { useState, useEffect } from 'preact/hooks';
import type { JSXInternal } from 'preact/src/jsx';

/**
 * Setting component for plugin configuration
 * Handles API token and notification settings
 */
export function Setting(): JSXInternal.Element {
  const [apiToken, setApiToken] = useState('');
  const [notificationsEnabled, setNotificationsEnabled] = useState(true);
  const i18n = window.Blinko.i18n;

  // Fetch initial plugin configuration on component mount
  useEffect(() => {
    window.Blinko.api.config.getPluginConfig.query({
      pluginName: 'my-note-plugin'
    }).then((res: any) => {
      setApiToken(res.apiToken)
    })
  }, []);

  /**
   * Handles saving of plugin settings
   * Saves API token and closes settings panel
   */
  const handleSave = async () => {
    window.Blinko.toast.success(i18n.t('settingsSaved'));
    window.Blinko.closeDialog();
    await window.Blinko.api.config.setPluginConfig.mutate({
      pluginName: 'my-note-plugin',
      key: 'apiToken',
      value: apiToken
    });
    window.Blinko.api.config.getPluginConfig.query({
      pluginName: 'my-note-plugin'
    });
  };

  return (
    <div class="max-w-2xl mx-auto p-2 rounded-lg">
      {/* API Token Input Section */}
      <div class="mb-6">
        <label class="block text-sm font-medium mb-2">
          {i18n.t('apiTokenLabel')}
          <input
            value={apiToken}
            onChange={(e) => setApiToken(e.currentTarget.value)}
            placeholder={i18n.t('enterApiToken')}
            class="mt-1 block w-full px-3 py-2 border rounded-md shadow-sm sm:text-sm bg-primary!"
          />
        </label>
      </div>

      {/* Notification Settings Section */}
      <div class="mb-6">
        <label class="flex items-center space-x-2">
          <input
            type="checkbox"
            checked={notificationsEnabled}
            onChange={(e) => setNotificationsEnabled(e.currentTarget.checked)}
            class="h-4 w-4 text-primary-foreground bg-primary rounded"
          />
          <span class="text-sm text-desc">{i18n.t('enableNotifications')}</span>
        </label>
      </div>

      {/* Save Button */}
      <button
        onClick={handleSave}
        class="inline-flex justify-center py-2 px-4 border border-transparent shadow-sm text-sm font-medium rounded-md bg-primary text-primary-foreground"
      >
        {i18n.t('saveSettings')}
      </button>
    </div>
  );
}
```

## 配置API

Blinko提供配置API用于保存和检索插件设置：

```typescript theme={null}
interface ConfigAPI {
  getPluginConfig: {
    query: (params: { pluginName: string }) => Promise<any>;
  };
  setPluginConfig: {
    mutate: (params: { 
      pluginName: string;
      key: string;
      value: any;
    }) => Promise<void>;
  };
}
```

## 在插件中使用配置

您可以在插件的其他部分访问和使用这些设置：

```typescript theme={null}
export class MyPlugin extends BasePlugin {
  private pluginName = 'my-note-plugin';

  async init() {
    // Load configuration
    const config = await window.Blinko.api.config.getPluginConfig.query({
      pluginName: this.pluginName
    });
    
    // Initialize features based on config
    if (config.apiToken) {
      this.initializeAPI(config.apiToken);
    }
  }

  private initializeAPI(apiToken: string) {
    // API initialization logic
  }
}
```

## 最佳实践

1. **类型安全**
   * 为您的配置使用TypeScript类型
   * 为您的插件设置定义接口

```typescript theme={null}
interface PluginConfig {
  apiToken: string;
  notificationsEnabled: boolean;
}

// Type-safe config access
const config = await window.Blinko.api.config.getPluginConfig.query<PluginConfig>({
  pluginName: 'my-note-plugin'
});
```

2. **国际化**
   * 对所有文本使用Blinko的i18n系统
   * 为所有设置标签提供翻译

```typescript theme={null}
// i18n usage example
const i18n = window.Blinko.i18n;

<label>{i18n.t('settings.apiToken.label')}</label>
<span>{i18n.t('settings.notifications.enable')}</span>
```

3. **错误处理**
   * 优雅地处理API错误
   * 为操作提供用户反馈

```typescript theme={null}
const handleSave = async () => {
  try {
    await window.Blinko.api.config.setPluginConfig.mutate({
      pluginName: 'my-note-plugin',
      key: 'apiToken',
      value: apiToken
    });
    window.Blinko.toast.success(i18n.t('settings.saved'));
  } catch (error) {
    window.Blinko.toast.error(i18n.t('settings.saveError'));
  }
};
```

4. **UI/UX最佳实践**
   * 使用与Blinko主题一致的样式
   * 为用户操作提供即时反馈
   * 使用适当的输入类型和验证

```typescript theme={null}
<input
  type="text"
  class="mt-1 block w-full px-3 py-2 border rounded-md shadow-sm"
  pattern="[A-Za-z0-9]+"
  required
  aria-label={i18n.t('settings.apiToken.label')}
/>
```
