From f7f7556b984484c2b3f039a1f6b55cbb3b6a4735 Mon Sep 17 00:00:00 2001 From: Julian Freeman Date: Mon, 23 Feb 2026 18:54:59 -0400 Subject: [PATCH] support api profiles --- src/App.vue | 114 +++++++++++++++++++++++++++++++++++++++-- src/stores/settings.ts | 10 ++++ 2 files changed, 120 insertions(+), 4 deletions(-) diff --git a/src/App.vue b/src/App.vue index 511e3b6..f9b33ca 100644 --- a/src/App.vue +++ b/src/App.vue @@ -14,7 +14,10 @@ import { Sun, Moon, User, - Type + Type, + Plus, + Save, + Play } from 'lucide-vue-next'; import { invoke } from '@tauri-apps/api/core'; import { listen } from '@tauri-apps/api/event'; @@ -23,7 +26,8 @@ import { LANGUAGES, DEFAULT_TEMPLATE, SPEAKER_IDENTITY_OPTIONS, - TONE_REGISTER_OPTIONS + TONE_REGISTER_OPTIONS, + type ApiProfile } from './stores/settings'; import pkg from '../package.json'; import { clsx, type ClassValue } from 'clsx'; @@ -50,6 +54,36 @@ const toggleTheme = () => { const view = ref<'translate' | 'settings' | 'logs'>('translate'); +// Profile Management +const newProfileName = ref(''); +const isSavingProfile = ref(false); + +const saveCurrentAsProfile = () => { + if (!newProfileName.value.trim()) return; + + const newProfile: ApiProfile = { + id: crypto.randomUUID(), + name: newProfileName.value.trim(), + apiBaseUrl: settings.apiBaseUrl, + apiKey: settings.apiKey, + modelName: settings.modelName + }; + + settings.profiles.push(newProfile); + newProfileName.value = ''; + isSavingProfile.value = false; +}; + +const applyProfile = (p: ApiProfile) => { + settings.apiBaseUrl = p.apiBaseUrl; + settings.apiKey = p.apiKey; + settings.modelName = p.modelName; +}; + +const deleteProfile = (id: string) => { + settings.profiles = settings.profiles.filter(p => p.id !== id); +}; + // Dropdown State const sourceDropdownOpen = ref(false); const targetDropdownOpen = ref(false); @@ -466,7 +500,79 @@ const translate = async () => {
-

模型接口配置

+

API 配置预设

+
+
+ 暂无预设配置 +
+
+
+ {{ profile.name }} +
+ {{ profile.modelName }} + + {{ profile.apiBaseUrl }} +
+
+
+ + +
+
+
+
+ +
+
+

模型接口配置

+
+ +
+
+ + + +
+
@@ -571,7 +677,7 @@ const translate = async () => { )" >{{ log.type === 'request' ? '请求' : log.type === 'response' ? '响应' : '错误' }}
-
{{ typeof log.content === 'object' ? JSON.stringify(log.content, null, 2) : log.content }}
+
{{ typeof log.content === 'object' ? JSON.stringify(log.content, null, 2) : log.content }}
diff --git a/src/stores/settings.ts b/src/stores/settings.ts index f03c6ad..bfbf207 100644 --- a/src/stores/settings.ts +++ b/src/stores/settings.ts @@ -54,11 +54,20 @@ Produce only the {TARGET_LANG} translation, without any additional explanations {TEXT}`; +export interface ApiProfile { + id: string; + name: string; + apiBaseUrl: string; + apiKey: string; + modelName: string; +} + export const useSettingsStore = defineStore('settings', () => { const isDark = useLocalStorage('is-dark', false); const apiBaseUrl = useLocalStorage('api-base-url', 'http://localhost:11434/v1'); const apiKey = useLocalStorage('api-key', ''); const modelName = useLocalStorage('model-name', 'translategemma:12b'); + const profiles = useLocalStorage('api-profiles', []); const enableStreaming = useLocalStorage('enable-streaming', true); const systemPromptTemplate = useLocalStorage('system-prompt-template', DEFAULT_TEMPLATE); @@ -88,6 +97,7 @@ export const useSettingsStore = defineStore('settings', () => { apiBaseUrl, apiKey, modelName, + profiles, enableStreaming, systemPromptTemplate, sourceLang,