feat(ai-config): persist AI settings per provider (#2412)

## 背景说明
AI 设置原本只有一个配置槽,切换模型厂商时会覆盖之前填写的 endpoint、API Key、model 等信息。本次改动让每个模型厂商各自保存一份配置,并在设置页和对话窗口提供已配置状态与快速切换能力。

## 修改内容
- 新增 ai_provider_configs 存储表,用于按 provider 保存独立 AI 配置
- 新增 Tauri/Web API:保存和加载 provider 级 AI 配置
- 设置页 provider 下拉展示“当前/已配置”状态
- 设置页切换 provider 前会先保存当前表单编辑内容,避免未保存输入丢失
- 对话窗口模型选择器支持查看并切换已配置过的其他 provider
- provider 配置保存时强制 config.provider 与 provider key 一致,避免错位配置污染
- 所有语言补齐新增 i18n 文案

## 修复的问题
- 切换模型厂商时原厂商配置会丢失
- 设置页切换 provider 时本地表单编辑态可能未保存
- provider key 与 config.provider 不一致时可能激活错误厂商
- 对话窗口模型选择器只能看到当前 provider 的模型,不能看到其他已配置厂商

## 测试
- npx tsc --noEmit
- cargo check -p dbx-core
- cargo check -p dbx-web
- cargo check --manifest-path src-tauri/Cargo.toml
This commit is contained in:
Abeautifulsnow authored and GitHub committed 2026-07-02 14:24:57 +08:00
1 parent 486b9ee8ed
commit a0754206d3
18 files changed
+301 -51

No files matched your search

+20
View File
@@ -27,6 +27,26 @@ pub async fn load_ai_config(state: State<'_, Arc<AppState>>) -> Result<Option<Ai
state.storage.load_ai_config().await
}
#[tauri::command]
pub async fn save_ai_provider_config(
state: State<'_, Arc<AppState>>,
provider: String,
config: AiConfig,
) -> Result<(), String> {
let parsed_provider: AiProvider = serde_json::from_value(serde_json::Value::String(provider.clone()))
.map_err(|_| format!("Invalid AI provider: {provider}"))?;
let mut config = config;
config.provider = parsed_provider;
state.storage.save_ai_provider_config(&provider, &config).await
}
#[tauri::command]
pub async fn load_ai_provider_configs(
state: State<'_, Arc<AppState>>,
) -> Result<std::collections::HashMap<String, AiConfig>, String> {
state.storage.load_ai_provider_configs().await
}
#[tauri::command]
pub async fn ai_complete(request: AiCompletionRequest) -> Result<String, String> {
dbx_core::ai::complete(&request).await