You've already forked iFlow-Settings-Editor-GUI
架构 API配置切换逻辑从多文件改为单文件内apiProfiles管理
This commit is contained in:
261
main.js
261
main.js
@@ -3,14 +3,11 @@ const path = require('path')
|
|||||||
const fs = require('fs')
|
const fs = require('fs')
|
||||||
|
|
||||||
console.log('main.js loaded')
|
console.log('main.js loaded')
|
||||||
console.log('app.getPath(\"home\"):', app.getPath('home'))
|
console.log('app.getPath("home"):', app.getPath('home'))
|
||||||
|
|
||||||
const DEFAULT_SETTINGS_FILE = path.join(app.getPath('home'), '.iflow', 'settings.json')
|
const SETTINGS_FILE = path.join(app.getPath('home'), '.iflow', 'settings.json')
|
||||||
const CONFIG_DIR = path.join(app.getPath('home'), '.iflow', 'configs')
|
console.log('SETTINGS_FILE:', SETTINGS_FILE)
|
||||||
console.log('DEFAULT_SETTINGS_FILE:', DEFAULT_SETTINGS_FILE)
|
|
||||||
console.log('CONFIG_DIR:', CONFIG_DIR)
|
|
||||||
|
|
||||||
let currentSettingsFile = DEFAULT_SETTINGS_FILE
|
|
||||||
let mainWindow
|
let mainWindow
|
||||||
|
|
||||||
const isDev = process.argv.includes('--dev')
|
const isDev = process.argv.includes('--dev')
|
||||||
@@ -88,91 +85,206 @@ ipcMain.on('window-close', () => mainWindow.close())
|
|||||||
|
|
||||||
ipcMain.handle('is-maximized', () => mainWindow.isMaximized())
|
ipcMain.handle('is-maximized', () => mainWindow.isMaximized())
|
||||||
|
|
||||||
// Get current config file path
|
// API 配置相关的字段
|
||||||
ipcMain.handle('get-current-config', () => {
|
const API_FIELDS = ['selectedAuthType', 'apiKey', 'baseUrl', 'modelName', 'searchApiKey', 'cna']
|
||||||
return { filePath: currentSettingsFile, fileName: path.basename(currentSettingsFile) }
|
|
||||||
})
|
|
||||||
|
|
||||||
// List all config files
|
// 读取设置文件
|
||||||
ipcMain.handle('list-configs', async () => {
|
function readSettings() {
|
||||||
|
if (!fs.existsSync(SETTINGS_FILE)) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
const data = fs.readFileSync(SETTINGS_FILE, 'utf-8')
|
||||||
|
return JSON.parse(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 写入设置文件
|
||||||
|
function writeSettings(data) {
|
||||||
|
if (fs.existsSync(SETTINGS_FILE)) {
|
||||||
|
const backupPath = SETTINGS_FILE + '.bak'
|
||||||
|
fs.copyFileSync(SETTINGS_FILE, backupPath)
|
||||||
|
}
|
||||||
|
fs.writeFileSync(SETTINGS_FILE, JSON.stringify(data, null, 2), 'utf-8')
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取 API 配置列表
|
||||||
|
ipcMain.handle('list-api-profiles', async () => {
|
||||||
try {
|
try {
|
||||||
const configs = []
|
const settings = readSettings()
|
||||||
// Always include default settings
|
if (!settings) {
|
||||||
if (fs.existsSync(DEFAULT_SETTINGS_FILE)) {
|
return { success: false, error: '配置文件不存在', profiles: [], currentProfile: '' }
|
||||||
const stats = fs.statSync(DEFAULT_SETTINGS_FILE)
|
|
||||||
configs.push({
|
|
||||||
name: '默认配置',
|
|
||||||
filePath: DEFAULT_SETTINGS_FILE,
|
|
||||||
modified: stats.mtime
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
// Add configs from CONFIG_DIR
|
|
||||||
if (fs.existsSync(CONFIG_DIR)) {
|
const profiles = settings.apiProfiles || {}
|
||||||
const files = fs.readdirSync(CONFIG_DIR).filter(f => f.endsWith('.json'))
|
const profileList = Object.keys(profiles).map(name => ({
|
||||||
for (const file of files) {
|
name,
|
||||||
const filePath = path.join(CONFIG_DIR, file)
|
isDefault: name === 'default'
|
||||||
const stats = fs.statSync(filePath)
|
}))
|
||||||
configs.push({
|
|
||||||
name: file.replace('.json', ''),
|
return {
|
||||||
filePath: filePath,
|
success: true,
|
||||||
modified: stats.mtime
|
profiles: profileList,
|
||||||
})
|
currentProfile: settings.currentApiProfile || 'default'
|
||||||
}
|
|
||||||
} else {
|
|
||||||
fs.mkdirSync(CONFIG_DIR, { recursive: true })
|
|
||||||
}
|
}
|
||||||
return { success: true, configs: configs }
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return { success: false, error: error.message, configs: [] }
|
return { success: false, error: error.message, profiles: [], currentProfile: '' }
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// Create new config
|
// 切换 API 配置
|
||||||
ipcMain.handle('create-config', async (event, name) => {
|
ipcMain.handle('switch-api-profile', async (event, profileName) => {
|
||||||
try {
|
try {
|
||||||
if (!fs.existsSync(CONFIG_DIR)) {
|
const settings = readSettings()
|
||||||
fs.mkdirSync(CONFIG_DIR, { recursive: true })
|
if (!settings) {
|
||||||
|
return { success: false, error: '配置文件不存在' }
|
||||||
}
|
}
|
||||||
const fileName = name + '.json'
|
|
||||||
const filePath = path.join(CONFIG_DIR, fileName)
|
const profiles = settings.apiProfiles || {}
|
||||||
if (fs.existsSync(filePath)) {
|
if (!profiles[profileName]) {
|
||||||
return { success: false, error: '配置文件已存在' }
|
return { success: false, error: `配置 "${profileName}" 不存在` }
|
||||||
}
|
}
|
||||||
let data = {}
|
|
||||||
if (fs.existsSync(currentSettingsFile)) {
|
// 保存当前配置到 apiProfiles(如果当前配置存在)
|
||||||
const content = fs.readFileSync(currentSettingsFile, 'utf-8')
|
const currentProfile = settings.currentApiProfile || 'default'
|
||||||
data = JSON.parse(content)
|
if (profiles[currentProfile]) {
|
||||||
|
const currentConfig = {}
|
||||||
|
for (const field of API_FIELDS) {
|
||||||
|
if (settings[field] !== undefined) {
|
||||||
|
currentConfig[field] = settings[field]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
profiles[currentProfile] = currentConfig
|
||||||
}
|
}
|
||||||
fs.writeFileSync(filePath, JSON.stringify(data, null, 2), 'utf-8')
|
|
||||||
return { success: true, filePath: filePath }
|
// 从 apiProfiles 加载新配置到主字段
|
||||||
|
const newConfig = profiles[profileName]
|
||||||
|
for (const field of API_FIELDS) {
|
||||||
|
if (newConfig[field] !== undefined) {
|
||||||
|
settings[field] = newConfig[field]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
settings.currentApiProfile = profileName
|
||||||
|
settings.apiProfiles = profiles
|
||||||
|
|
||||||
|
writeSettings(settings)
|
||||||
|
|
||||||
|
return { success: true, data: settings }
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return { success: false, error: error.message }
|
return { success: false, error: error.message }
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// Delete config
|
// 创建新的 API 配置
|
||||||
ipcMain.handle('delete-config', async (event, filePath) => {
|
ipcMain.handle('create-api-profile', async (event, name) => {
|
||||||
try {
|
try {
|
||||||
if (filePath === DEFAULT_SETTINGS_FILE) {
|
const settings = readSettings()
|
||||||
return { success: false, error: '不能删除默认配置' }
|
if (!settings) {
|
||||||
|
return { success: false, error: '配置文件不存在' }
|
||||||
}
|
}
|
||||||
if (fs.existsSync(filePath)) {
|
|
||||||
fs.unlinkSync(filePath)
|
if (!settings.apiProfiles) {
|
||||||
|
settings.apiProfiles = { default: {} }
|
||||||
|
// 初始化 default 配置
|
||||||
|
for (const field of API_FIELDS) {
|
||||||
|
if (settings[field] !== undefined) {
|
||||||
|
settings.apiProfiles.default[field] = settings[field]
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (settings.apiProfiles[name]) {
|
||||||
|
return { success: false, error: `配置 "${name}" 已存在` }
|
||||||
|
}
|
||||||
|
|
||||||
|
// 复制当前配置到新配置
|
||||||
|
const newConfig = {}
|
||||||
|
for (const field of API_FIELDS) {
|
||||||
|
if (settings[field] !== undefined) {
|
||||||
|
newConfig[field] = settings[field]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
settings.apiProfiles[name] = newConfig
|
||||||
|
|
||||||
|
writeSettings(settings)
|
||||||
|
|
||||||
return { success: true }
|
return { success: true }
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return { success: false, error: error.message }
|
return { success: false, error: error.message }
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// Switch to config
|
// 删除 API 配置
|
||||||
ipcMain.handle('switch-config', async (event, filePath) => {
|
ipcMain.handle('delete-api-profile', async (event, name) => {
|
||||||
try {
|
try {
|
||||||
if (!fs.existsSync(filePath)) {
|
const settings = readSettings()
|
||||||
|
if (!settings) {
|
||||||
return { success: false, error: '配置文件不存在' }
|
return { success: false, error: '配置文件不存在' }
|
||||||
}
|
}
|
||||||
currentSettingsFile = filePath
|
|
||||||
return { success: true, filePath: currentSettingsFile }
|
if (name === 'default') {
|
||||||
|
return { success: false, error: '不能删除默认配置' }
|
||||||
|
}
|
||||||
|
|
||||||
|
const profiles = settings.apiProfiles || {}
|
||||||
|
if (!profiles[name]) {
|
||||||
|
return { success: false, error: `配置 "${name}" 不存在` }
|
||||||
|
}
|
||||||
|
|
||||||
|
delete profiles[name]
|
||||||
|
settings.apiProfiles = profiles
|
||||||
|
|
||||||
|
// 如果删除的是当前配置,切换到 default
|
||||||
|
if (settings.currentApiProfile === name) {
|
||||||
|
settings.currentApiProfile = 'default'
|
||||||
|
if (profiles.default) {
|
||||||
|
for (const field of API_FIELDS) {
|
||||||
|
if (profiles.default[field] !== undefined) {
|
||||||
|
settings[field] = profiles.default[field]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
writeSettings(settings)
|
||||||
|
|
||||||
|
return { success: true, data: settings }
|
||||||
|
} catch (error) {
|
||||||
|
return { success: false, error: error.message }
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// 重命名 API 配置
|
||||||
|
ipcMain.handle('rename-api-profile', async (event, oldName, newName) => {
|
||||||
|
try {
|
||||||
|
const settings = readSettings()
|
||||||
|
if (!settings) {
|
||||||
|
return { success: false, error: '配置文件不存在' }
|
||||||
|
}
|
||||||
|
|
||||||
|
if (oldName === 'default') {
|
||||||
|
return { success: false, error: '不能重命名默认配置' }
|
||||||
|
}
|
||||||
|
|
||||||
|
const profiles = settings.apiProfiles || {}
|
||||||
|
if (!profiles[oldName]) {
|
||||||
|
return { success: false, error: `配置 "${oldName}" 不存在` }
|
||||||
|
}
|
||||||
|
|
||||||
|
if (profiles[newName]) {
|
||||||
|
return { success: false, error: `配置 "${newName}" 已存在` }
|
||||||
|
}
|
||||||
|
|
||||||
|
profiles[newName] = profiles[oldName]
|
||||||
|
delete profiles[oldName]
|
||||||
|
settings.apiProfiles = profiles
|
||||||
|
|
||||||
|
if (settings.currentApiProfile === oldName) {
|
||||||
|
settings.currentApiProfile = newName
|
||||||
|
}
|
||||||
|
|
||||||
|
writeSettings(settings)
|
||||||
|
|
||||||
|
return { success: true }
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return { success: false, error: error.message }
|
return { success: false, error: error.message }
|
||||||
}
|
}
|
||||||
@@ -181,10 +293,10 @@ ipcMain.handle('switch-config', async (event, filePath) => {
|
|||||||
// IPC Handlers
|
// IPC Handlers
|
||||||
ipcMain.handle('load-settings', async () => {
|
ipcMain.handle('load-settings', async () => {
|
||||||
try {
|
try {
|
||||||
if (!fs.existsSync(currentSettingsFile)) {
|
if (!fs.existsSync(SETTINGS_FILE)) {
|
||||||
return { success: false, error: 'File not found', data: null }
|
return { success: false, error: 'File not found', data: null }
|
||||||
}
|
}
|
||||||
const data = fs.readFileSync(currentSettingsFile, 'utf-8')
|
const data = fs.readFileSync(SETTINGS_FILE, 'utf-8')
|
||||||
const json = JSON.parse(data)
|
const json = JSON.parse(data)
|
||||||
return { success: true, data: json }
|
return { success: true, data: json }
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -194,11 +306,22 @@ ipcMain.handle('load-settings', async () => {
|
|||||||
|
|
||||||
ipcMain.handle('save-settings', async (event, data) => {
|
ipcMain.handle('save-settings', async (event, data) => {
|
||||||
try {
|
try {
|
||||||
if (fs.existsSync(currentSettingsFile)) {
|
// 保存时同步更新 apiProfiles 中的当前配置
|
||||||
const backupPath = currentSettingsFile + '.bak'
|
const currentProfile = data.currentApiProfile || 'default'
|
||||||
fs.copyFileSync(currentSettingsFile, backupPath)
|
if (!data.apiProfiles) {
|
||||||
|
data.apiProfiles = {}
|
||||||
}
|
}
|
||||||
fs.writeFileSync(currentSettingsFile, JSON.stringify(data, null, 2), 'utf-8')
|
|
||||||
|
// 更新当前配置到 apiProfiles
|
||||||
|
const currentConfig = {}
|
||||||
|
for (const field of API_FIELDS) {
|
||||||
|
if (data[field] !== undefined) {
|
||||||
|
currentConfig[field] = data[field]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
data.apiProfiles[currentProfile] = currentConfig
|
||||||
|
|
||||||
|
writeSettings(data)
|
||||||
return { success: true }
|
return { success: true }
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return { success: false, error: error.message }
|
return { success: false, error: error.message }
|
||||||
@@ -207,4 +330,4 @@ ipcMain.handle('save-settings', async (event, data) => {
|
|||||||
|
|
||||||
ipcMain.handle('show-message', async (event, { type, title, message }) => {
|
ipcMain.handle('show-message', async (event, { type, title, message }) => {
|
||||||
return dialog.showMessageBox(mainWindow, { type, title, message })
|
return dialog.showMessageBox(mainWindow, { type, title, message })
|
||||||
})
|
})
|
||||||
18
preload.js
18
preload.js
@@ -1,17 +1,21 @@
|
|||||||
const { contextBridge, ipcRenderer } = require('electron')
|
const { contextBridge, ipcRenderer } = require('electron')
|
||||||
|
|
||||||
contextBridge.exposeInMainWorld('electronAPI', {
|
contextBridge.exposeInMainWorld('electronAPI', {
|
||||||
|
// 基本设置操作
|
||||||
loadSettings: () => ipcRenderer.invoke('load-settings'),
|
loadSettings: () => ipcRenderer.invoke('load-settings'),
|
||||||
saveSettings: (data) => ipcRenderer.invoke('save-settings', data),
|
saveSettings: (data) => ipcRenderer.invoke('save-settings', data),
|
||||||
showMessage: (options) => ipcRenderer.invoke('show-message', options),
|
showMessage: (options) => ipcRenderer.invoke('show-message', options),
|
||||||
|
|
||||||
|
// 窗口控制
|
||||||
isMaximized: () => ipcRenderer.invoke('is-maximized'),
|
isMaximized: () => ipcRenderer.invoke('is-maximized'),
|
||||||
minimize: () => ipcRenderer.send('window-minimize'),
|
minimize: () => ipcRenderer.send('window-minimize'),
|
||||||
maximize: () => ipcRenderer.send('window-maximize'),
|
maximize: () => ipcRenderer.send('window-maximize'),
|
||||||
close: () => ipcRenderer.send('window-close'),
|
close: () => ipcRenderer.send('window-close'),
|
||||||
getCurrentConfig: () => ipcRenderer.invoke('get-current-config'),
|
|
||||||
listConfigs: () => ipcRenderer.invoke('list-configs'),
|
// API 配置管理(单文件内多配置)
|
||||||
createConfig: (name) => ipcRenderer.invoke('create-config', name),
|
listApiProfiles: () => ipcRenderer.invoke('list-api-profiles'),
|
||||||
deleteConfig: (filePath) => ipcRenderer.invoke('delete-config', filePath),
|
switchApiProfile: (profileName) => ipcRenderer.invoke('switch-api-profile', profileName),
|
||||||
switchConfig: (filePath) => ipcRenderer.invoke('switch-config', filePath)
|
createApiProfile: (name) => ipcRenderer.invoke('create-api-profile', name),
|
||||||
})
|
deleteApiProfile: (name) => ipcRenderer.invoke('delete-api-profile', name),
|
||||||
|
renameApiProfile: (oldName, newName) => ipcRenderer.invoke('rename-api-profile', oldName, newName)
|
||||||
|
})
|
||||||
106
src/App.vue
106
src/App.vue
@@ -126,17 +126,17 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="form-row">
|
<div class="form-row">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="form-label">当前配置文件</label>
|
<label class="form-label">当前配置</label>
|
||||||
<select class="form-select" v-model="currentConfigFilePath" @change="switchConfig">
|
<select class="form-select" v-model="currentApiProfile" @change="switchApiProfile">
|
||||||
<option v-for="cfg in configList" :key="cfg.filePath" :value="cfg.filePath">{{ cfg.name }}</option>
|
<option v-for="profile in apiProfiles" :key="profile.name" :value="profile.name">{{ profile.name }}</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group" style="display: flex; align-items: flex-end; gap: 8px;">
|
<div class="form-group" style="display: flex; align-items: flex-end; gap: 8px;">
|
||||||
<button class="btn btn-secondary" @click="createNewConfig" style="height: 40px;">
|
<button class="btn btn-secondary" @click="createNewApiProfile" style="height: 40px;">
|
||||||
<Add size="14" />
|
<Add size="14" />
|
||||||
新建
|
新建
|
||||||
</button>
|
</button>
|
||||||
<button class="btn btn-danger" @click="deleteConfig" style="height: 40px;" :disabled="configList.length <= 1">
|
<button class="btn btn-danger" @click="deleteApiProfile" style="height: 40px;" :disabled="currentApiProfile === 'default'">
|
||||||
<Delete size="14" />
|
<Delete size="14" />
|
||||||
删除
|
删除
|
||||||
</button>
|
</button>
|
||||||
@@ -263,7 +263,7 @@
|
|||||||
<footer class="footer">
|
<footer class="footer">
|
||||||
<div class="footer-status">
|
<div class="footer-status">
|
||||||
<div class="footer-status-dot"></div>
|
<div class="footer-status-dot"></div>
|
||||||
<span>{{ currentConfigFilePath }}</span>
|
<span>配置: {{ currentApiProfile || 'default' }}</span>
|
||||||
</div>
|
</div>
|
||||||
<span :class="{ 'footer-modified': modified }">{{ modified ? '● 已修改' : '✓ 未修改' }}</span>
|
<span :class="{ 'footer-modified': modified }">{{ modified ? '● 已修改' : '✓ 未修改' }}</span>
|
||||||
</footer>
|
</footer>
|
||||||
@@ -306,7 +306,9 @@ const settings = ref({
|
|||||||
baseUrl: '',
|
baseUrl: '',
|
||||||
modelName: '',
|
modelName: '',
|
||||||
searchApiKey: '',
|
searchApiKey: '',
|
||||||
cna: ''
|
cna: '',
|
||||||
|
currentApiProfile: 'default',
|
||||||
|
apiProfiles: { default: {} }
|
||||||
});
|
});
|
||||||
|
|
||||||
const originalSettings = ref({});
|
const originalSettings = ref({});
|
||||||
@@ -314,73 +316,83 @@ const modified = ref(false);
|
|||||||
const currentSection = ref('general');
|
const currentSection = ref('general');
|
||||||
const currentServerName = ref(null);
|
const currentServerName = ref(null);
|
||||||
const isLoading = ref(true);
|
const isLoading = ref(true);
|
||||||
const configList = ref([]);
|
const apiProfiles = ref([]);
|
||||||
const currentConfigFilePath = ref('');
|
const currentApiProfile = ref('default');
|
||||||
const showInputDialog = ref({ show: false, title: '', placeholder: '', callback: null });
|
const showInputDialog = ref({ show: false, title: '', placeholder: '', callback: null });
|
||||||
const inputDialogValue = ref('');
|
const inputDialogValue = ref('');
|
||||||
|
|
||||||
// Load config list
|
// Load API profiles list
|
||||||
const loadConfigList = async () => {
|
const loadApiProfiles = async () => {
|
||||||
const result = await window.electronAPI.listConfigs();
|
const result = await window.electronAPI.listApiProfiles();
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
configList.value = result.configs;
|
apiProfiles.value = result.profiles;
|
||||||
|
currentApiProfile.value = result.currentProfile;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Switch config
|
// Switch API profile
|
||||||
const switchConfig = async () => {
|
const switchApiProfile = async () => {
|
||||||
if (modified.value) {
|
if (modified.value) {
|
||||||
const confirmed = await new Promise((resolve) => {
|
const confirmed = await new Promise((resolve) => {
|
||||||
showInputDialog.value = { show: true, title: '切换配置', placeholder: '当前有未保存的更改,切换配置将丢失这些更改,确定要切换吗?', callback: resolve, isConfirm: true };
|
showInputDialog.value = { show: true, title: '切换配置', placeholder: '当前有未保存的更改,切换配置将丢失这些更改,确定要切换吗?', callback: resolve, isConfirm: true };
|
||||||
});
|
});
|
||||||
if (!confirmed) return;
|
if (!confirmed) {
|
||||||
}
|
// 恢复到之前的值
|
||||||
if (currentConfigFilePath.value) {
|
const result = await window.electronAPI.listApiProfiles();
|
||||||
const result = await window.electronAPI.switchConfig(currentConfigFilePath.value);
|
if (result.success) {
|
||||||
if (result.success) {
|
currentApiProfile.value = result.currentProfile;
|
||||||
await loadSettings();
|
}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
const result = await window.electronAPI.switchApiProfile(currentApiProfile.value);
|
||||||
|
if (result.success) {
|
||||||
|
const data = JSON.parse(JSON.stringify(result.data));
|
||||||
|
if (!data.checkpointing) data.checkpointing = { enabled: true };
|
||||||
|
if (!data.mcpServers) data.mcpServers = {};
|
||||||
|
settings.value = data;
|
||||||
|
originalSettings.value = JSON.parse(JSON.stringify(data));
|
||||||
|
modified.value = false;
|
||||||
|
} else {
|
||||||
|
await window.electronAPI.showMessage({ type: 'error', title: '切换失败', message: result.error });
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Create new config
|
// Create new API profile
|
||||||
const createNewConfig = async () => {
|
const createNewApiProfile = async () => {
|
||||||
const name = await new Promise((resolve) => {
|
const name = await new Promise((resolve) => {
|
||||||
showInputDialog.value = { show: true, title: '新建配置文件', placeholder: '请输入配置名称', callback: resolve };
|
showInputDialog.value = { show: true, title: '新建配置', placeholder: '请输入配置名称', callback: resolve };
|
||||||
});
|
});
|
||||||
if (!name) return;
|
if (!name) return;
|
||||||
const result = await window.electronAPI.createConfig(name);
|
const result = await window.electronAPI.createApiProfile(name);
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
await loadConfigList();
|
await loadApiProfiles();
|
||||||
currentConfigFilePath.value = result.filePath;
|
await window.electronAPI.showMessage({ type: 'info', title: '创建成功', message: `配置 "${name}" 已创建` });
|
||||||
await loadSettings();
|
|
||||||
await window.electronAPI.showMessage({ type: 'info', title: '创建成功', message: `配置文件 "${name}" 已创建` });
|
|
||||||
} else {
|
} else {
|
||||||
await window.electronAPI.showMessage({ type: 'error', title: '创建失败', message: result.error });
|
await window.electronAPI.showMessage({ type: 'error', title: '创建失败', message: result.error });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Delete config
|
// Delete API profile
|
||||||
const deleteConfig = async () => {
|
const deleteApiProfile = async () => {
|
||||||
if (configList.value.length <= 1) {
|
if (currentApiProfile.value === 'default') {
|
||||||
await window.electronAPI.showMessage({ type: 'warning', title: '无法删除', message: '至少需要保留一个配置文件' });
|
await window.electronAPI.showMessage({ type: 'warning', title: '无法删除', message: '不能删除默认配置' });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const cfg = configList.value.find(c => c.filePath === currentConfigFilePath.value);
|
|
||||||
if (!cfg) return;
|
|
||||||
const confirmed = await new Promise((resolve) => {
|
const confirmed = await new Promise((resolve) => {
|
||||||
showInputDialog.value = { show: true, title: '删除配置文件', placeholder: `确定要删除配置文件 "${cfg.name}" 吗?`, callback: resolve, isConfirm: true };
|
showInputDialog.value = { show: true, title: '删除配置', placeholder: `确定要删除配置 "${currentApiProfile.value}" 吗?`, callback: resolve, isConfirm: true };
|
||||||
});
|
});
|
||||||
if (!confirmed) return;
|
if (!confirmed) return;
|
||||||
const result = await window.electronAPI.deleteConfig(currentConfigFilePath.value);
|
const result = await window.electronAPI.deleteApiProfile(currentApiProfile.value);
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
await loadConfigList();
|
const data = JSON.parse(JSON.stringify(result.data));
|
||||||
if (configList.value.length > 0) {
|
if (!data.checkpointing) data.checkpointing = { enabled: true };
|
||||||
currentConfigFilePath.value = configList.value[0].filePath;
|
if (!data.mcpServers) data.mcpServers = {};
|
||||||
await window.electronAPI.switchConfig(currentConfigFilePath.value);
|
settings.value = data;
|
||||||
await loadSettings();
|
originalSettings.value = JSON.parse(JSON.stringify(data));
|
||||||
}
|
modified.value = false;
|
||||||
await window.electronAPI.showMessage({ type: 'info', title: '删除成功', message: `配置文件 "${cfg.name}" 已删除` });
|
await loadApiProfiles();
|
||||||
|
await window.electronAPI.showMessage({ type: 'info', title: '删除成功', message: `配置已删除` });
|
||||||
} else {
|
} else {
|
||||||
await window.electronAPI.showMessage({ type: 'error', title: '删除失败', message: result.error });
|
await window.electronAPI.showMessage({ type: 'error', title: '删除失败', message: result.error });
|
||||||
}
|
}
|
||||||
@@ -507,11 +519,7 @@ const closeInputDialog = (result) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
await loadConfigList();
|
await loadApiProfiles();
|
||||||
const current = await window.electronAPI.getCurrentConfig();
|
|
||||||
if (current.filePath) {
|
|
||||||
currentConfigFilePath.value = current.filePath;
|
|
||||||
}
|
|
||||||
await loadSettings();
|
await loadSettings();
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
Reference in New Issue
Block a user