mirror of
https://github.com/wwiinnddyy/LanMountainDesktop.git
synced 2026-06-23 01:44:26 +08:00
354 lines
8.7 KiB
Markdown
354 lines
8.7 KiB
Markdown
|
|
# 03-设置系统集成
|
|||
|
|
|
|||
|
|
设置系统允许插件在阑山桌面的设置窗口中添加自己的配置页面,让用户可以自定义插件行为。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 🎯 设置系统概述
|
|||
|
|
|
|||
|
|
阑山桌面提供两种设置页面模式:
|
|||
|
|
|
|||
|
|
| 模式 | 适用场景 | 复杂度 | 灵活性 |
|
|||
|
|
|-----|---------|--------|--------|
|
|||
|
|
| **声明式设置** | 简单的键值配置 | 低 | 中 |
|
|||
|
|
| **自定义设置页** | 复杂交互、自定义控件 | 中 | 高 |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 📝 声明式设置
|
|||
|
|
|
|||
|
|
通过链式 API 声明配置项,宿主自动生成设置页面。
|
|||
|
|
|
|||
|
|
### 基本用法
|
|||
|
|
|
|||
|
|
```csharp
|
|||
|
|
public override void Initialize(HostBuilderContext context, IServiceCollection services)
|
|||
|
|
{
|
|||
|
|
services.AddPluginSettingsSection(
|
|||
|
|
sectionId: "myplugin-settings", // 设置节唯一标识
|
|||
|
|
displayName: "我的插件设置", // 显示名称
|
|||
|
|
configure: section => // 配置设置项
|
|||
|
|
{
|
|||
|
|
section
|
|||
|
|
.AddToggle("enabled", "启用插件", defaultValue: true)
|
|||
|
|
.AddText("api_key", "API密钥", defaultValue: "")
|
|||
|
|
.AddNumber("interval", "刷新间隔(秒)", defaultValue: 60, minimum: 10, maximum: 3600)
|
|||
|
|
.AddSelect("theme", "主题", new[]
|
|||
|
|
{
|
|||
|
|
new SettingsOptionChoice("light", "浅色"),
|
|||
|
|
new SettingsOptionChoice("dark", "深色"),
|
|||
|
|
new SettingsOptionChoice("auto", "跟随系统")
|
|||
|
|
}, defaultValue: "auto");
|
|||
|
|
},
|
|||
|
|
iconKey: "Settings"); // 图标
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 支持的设置类型
|
|||
|
|
|
|||
|
|
| 方法 | 类型 | 用途 | 示例 |
|
|||
|
|
|-----|------|------|------|
|
|||
|
|
| `AddToggle` | 布尔 | 开关选项 | 启用/禁用 |
|
|||
|
|
| `AddText` | 字符串 | 文本输入 | API密钥、用户名 |
|
|||
|
|
| `AddNumber` | 数值 | 数字输入 | 刷新间隔、数量 |
|
|||
|
|
| `AddSelect` | 枚举 | 下拉选择 | 主题、语言 |
|
|||
|
|
| `AddPath` | 路径 | 文件/文件夹选择 | 保存路径 |
|
|||
|
|
| `AddList` | 列表 | 字符串列表 | 服务器地址列表 |
|
|||
|
|
|
|||
|
|
### 各类型详解
|
|||
|
|
|
|||
|
|
#### Toggle(开关)
|
|||
|
|
|
|||
|
|
```csharp
|
|||
|
|
.AddToggle(
|
|||
|
|
key: "auto_update", // 设置键
|
|||
|
|
displayName: "自动更新", // 显示名称
|
|||
|
|
defaultValue: true, // 默认值
|
|||
|
|
description: "启动时检查更新" // 可选描述
|
|||
|
|
)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### Text(文本)
|
|||
|
|
|
|||
|
|
```csharp
|
|||
|
|
.AddText(
|
|||
|
|
key: "api_key",
|
|||
|
|
displayName: "API密钥",
|
|||
|
|
defaultValue: "",
|
|||
|
|
placeholder: "请输入API密钥", // 占位符
|
|||
|
|
isPassword: true // 密码输入(掩码显示)
|
|||
|
|
)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### Number(数值)
|
|||
|
|
|
|||
|
|
```csharp
|
|||
|
|
.AddNumber(
|
|||
|
|
key: "refresh_interval",
|
|||
|
|
displayName: "刷新间隔",
|
|||
|
|
defaultValue: 60,
|
|||
|
|
minimum: 10, // 最小值
|
|||
|
|
maximum: 3600, // 最大值
|
|||
|
|
increment: 10 // 步进值
|
|||
|
|
)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### Select(选择)
|
|||
|
|
|
|||
|
|
```csharp
|
|||
|
|
.AddSelect(
|
|||
|
|
key: "display_mode",
|
|||
|
|
displayName: "显示模式",
|
|||
|
|
choices: new[]
|
|||
|
|
{
|
|||
|
|
new SettingsOptionChoice("compact", "紧凑"),
|
|||
|
|
new SettingsOptionChoice("normal", "标准"),
|
|||
|
|
new SettingsOptionChoice("detailed", "详细")
|
|||
|
|
},
|
|||
|
|
defaultValue: "normal"
|
|||
|
|
)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### Path(路径)
|
|||
|
|
|
|||
|
|
```csharp
|
|||
|
|
.AddPath(
|
|||
|
|
key: "save_location",
|
|||
|
|
displayName: "保存位置",
|
|||
|
|
defaultValue: "",
|
|||
|
|
pathType: SettingsPathType.Folder, // Folder 或 File
|
|||
|
|
dialogTitle: "选择保存文件夹"
|
|||
|
|
)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 🎨 自定义设置页
|
|||
|
|
|
|||
|
|
当声明式设置无法满足需求时,可以创建自定义设置页面。
|
|||
|
|
|
|||
|
|
### 步骤 1:创建设置页类
|
|||
|
|
|
|||
|
|
```csharp
|
|||
|
|
using LanMountainDesktop.PluginSdk;
|
|||
|
|
using FluentAvalonia.UI.Controls;
|
|||
|
|
|
|||
|
|
namespace MyPlugin;
|
|||
|
|
|
|||
|
|
public class MySettingsPage : SettingsPageBase
|
|||
|
|
{
|
|||
|
|
private readonly IPluginSettingsService _settingsService;
|
|||
|
|
|
|||
|
|
public MySettingsPage(IPluginSettingsService settingsService)
|
|||
|
|
{
|
|||
|
|
_settingsService = settingsService;
|
|||
|
|
InitializeComponent();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private void InitializeComponent()
|
|||
|
|
{
|
|||
|
|
// 创建页面内容
|
|||
|
|
var panel = new StackPanel { Spacing = 16 };
|
|||
|
|
|
|||
|
|
// 添加自定义控件
|
|||
|
|
var expander = new SettingsExpander
|
|||
|
|
{
|
|||
|
|
Header = "高级设置",
|
|||
|
|
Description = "配置插件的高级选项"
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
var toggle = new ToggleSwitch
|
|||
|
|
{
|
|||
|
|
Content = "启用实验性功能"
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
expander.Items.Add(toggle);
|
|||
|
|
panel.Children.Add(expander);
|
|||
|
|
|
|||
|
|
// 添加颜色选择器示例
|
|||
|
|
var colorPicker = new ColorPicker
|
|||
|
|
{
|
|||
|
|
Header = "主题颜色"
|
|||
|
|
};
|
|||
|
|
panel.Children.Add(colorPicker);
|
|||
|
|
|
|||
|
|
Content = panel;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 步骤 2:注册自定义设置页
|
|||
|
|
|
|||
|
|
```csharp
|
|||
|
|
public override void Initialize(HostBuilderContext context, IServiceCollection services)
|
|||
|
|
{
|
|||
|
|
services.AddPluginSettingsSection<MySettingsPage>(
|
|||
|
|
sectionId: "myplugin-advanced",
|
|||
|
|
displayName: "高级设置",
|
|||
|
|
iconKey: "Settings");
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 混合模式
|
|||
|
|
|
|||
|
|
可以同时使用声明式设置和自定义视图:
|
|||
|
|
|
|||
|
|
```csharp
|
|||
|
|
services.AddPluginSettingsSection(
|
|||
|
|
sectionId: "myplugin-settings",
|
|||
|
|
displayName: "插件设置",
|
|||
|
|
configure: section => section
|
|||
|
|
.SetCustomView<MyCustomSettingsPage>() // 设置自定义视图
|
|||
|
|
.AddToggle("enabled", "启用") // 同时声明设置项
|
|||
|
|
.AddText("api_key", "API密钥"),
|
|||
|
|
iconKey: "Settings");
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 💾 读取和保存设置
|
|||
|
|
|
|||
|
|
### 在服务中读取设置
|
|||
|
|
|
|||
|
|
```csharp
|
|||
|
|
public class WeatherService
|
|||
|
|
{
|
|||
|
|
private readonly IPluginSettingsService _settings;
|
|||
|
|
|
|||
|
|
public WeatherService(IPluginSettingsService settings)
|
|||
|
|
{
|
|||
|
|
_settings = settings;
|
|||
|
|
|
|||
|
|
// 读取设置
|
|||
|
|
var apiKey = _settings.GetValue<string>("api_key", "");
|
|||
|
|
var autoRefresh = _settings.GetValue<bool>("auto_update", true);
|
|||
|
|
var interval = _settings.GetValue<int>("refresh_interval", 60);
|
|||
|
|
|
|||
|
|
// 监听设置变化
|
|||
|
|
_settings.SettingsChanged += (sender, e) =>
|
|||
|
|
{
|
|||
|
|
if (e.Key == "refresh_interval")
|
|||
|
|
{
|
|||
|
|
UpdateTimerInterval(e.NewValue);
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 在组件中读取设置
|
|||
|
|
|
|||
|
|
```csharp
|
|||
|
|
public class WeatherWidget : Border
|
|||
|
|
{
|
|||
|
|
public WeatherWidget(PluginDesktopComponentContext context)
|
|||
|
|
{
|
|||
|
|
// 通过 context 获取设置
|
|||
|
|
var settings = context.Settings;
|
|||
|
|
|
|||
|
|
var city = settings.GetValue<string>("city", "北京");
|
|||
|
|
var unit = settings.GetValue<string>("temperature_unit", "celsius");
|
|||
|
|
|
|||
|
|
// 监听设置变化
|
|||
|
|
context.Settings.SettingsChanged += (_, e) =>
|
|||
|
|
{
|
|||
|
|
if (e.Key == "city")
|
|||
|
|
{
|
|||
|
|
RefreshWeather(e.NewValue);
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 保存设置
|
|||
|
|
|
|||
|
|
```csharp
|
|||
|
|
// 在设置页面中保存
|
|||
|
|
private void SaveButton_Click(object? sender, RoutedEventArgs e)
|
|||
|
|
{
|
|||
|
|
_settingsService.SetValue("api_key", ApiKeyTextBox.Text);
|
|||
|
|
_settingsService.SetValue("auto_update", AutoUpdateToggle.IsChecked ?? false);
|
|||
|
|
|
|||
|
|
// 设置会自动持久化,无需手动保存文件
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 🔔 设置变更通知
|
|||
|
|
|
|||
|
|
### 订阅变更事件
|
|||
|
|
|
|||
|
|
```csharp
|
|||
|
|
public class MyService
|
|||
|
|
{
|
|||
|
|
public MyService(IPluginSettingsService settings)
|
|||
|
|
{
|
|||
|
|
settings.SettingsChanged += OnSettingsChanged;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private void OnSettingsChanged(object? sender, SettingsChangedEvent e)
|
|||
|
|
{
|
|||
|
|
Console.WriteLine($"设置变更: {e.Key}");
|
|||
|
|
Console.WriteLine($"旧值: {e.OldValue}");
|
|||
|
|
Console.WriteLine($"新值: {e.NewValue}");
|
|||
|
|
|
|||
|
|
// 根据变更的键执行相应操作
|
|||
|
|
switch (e.Key)
|
|||
|
|
{
|
|||
|
|
case "refresh_interval":
|
|||
|
|
UpdateRefreshTimer((int)e.NewValue);
|
|||
|
|
break;
|
|||
|
|
case "theme":
|
|||
|
|
ApplyTheme((string)e.NewValue);
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 🐛 常见问题
|
|||
|
|
|
|||
|
|
### 问题 1:设置不保存
|
|||
|
|
|
|||
|
|
**排查:**
|
|||
|
|
1. 确认 `sectionId` 唯一且合法
|
|||
|
|
2. 检查设置键名是否正确
|
|||
|
|
3. 查看日志是否有权限错误
|
|||
|
|
|
|||
|
|
### 问题 2:设置页面不显示
|
|||
|
|
|
|||
|
|
**排查:**
|
|||
|
|
1. 确认已调用 `AddPluginSettingsSection`
|
|||
|
|
2. 检查 `sectionId` 是否唯一
|
|||
|
|
3. 确认设置页类是 `public`
|
|||
|
|
|
|||
|
|
### 问题 3:设置变更通知不触发
|
|||
|
|
|
|||
|
|
**原因:** 可能订阅的是不同实例
|
|||
|
|
|
|||
|
|
**解决:** 确保使用注入的 `IPluginSettingsService`
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 📚 参考资源
|
|||
|
|
|
|||
|
|
- [IPluginSettingsService 源码](../../LanMountainDesktop.PluginSdk/IPluginSettingsService.cs)
|
|||
|
|
- [SettingsPageBase 源码](../../LanMountainDesktop.PluginSdk/SettingsPageBase.cs)
|
|||
|
|
- [04-开发设置页面](../04-实战案例/04-开发设置页面.md)
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 🎯 下一步
|
|||
|
|
|
|||
|
|
学习外观系统:
|
|||
|
|
|
|||
|
|
👉 **[04-外观与主题系统](04-外观与主题系统.md)** - 适配宿主主题
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
*最后更新:2026年4月*
|