feat(initialization): 新增配置文件操作和管理员权限检查

- 新增配置文件保存、加载和重置功能
- 添加管理员权限检查和重启为管理员的功能
- 实现 pip 包管理器安装功能
- 优化初始化流程,自动检测并安装依赖
This commit is contained in:
2025-08-07 20:18:53 +08:00
parent e7f898f357
commit 0171c3ca4d
15 changed files with 2397 additions and 8 deletions

View File

@@ -0,0 +1,163 @@
import { createComponentLogger } from './logger'
import type { ThemeMode, ThemeColor } from '@/composables/useTheme'
const logger = createComponentLogger('Config')
export interface FrontendConfig {
// 基础配置
isFirstLaunch: boolean
init: boolean
lastUpdateCheck?: string
// 主题设置
themeMode: ThemeMode
themeColor: ThemeColor
// 镜像源设置
selectedGitMirror: string
selectedPythonMirror: string
selectedPipMirror: string
// 安装状态
pythonInstalled?: boolean
gitInstalled?: boolean
backendExists?: boolean
dependenciesInstalled?: boolean
pipInstalled?: boolean
}
const DEFAULT_CONFIG: FrontendConfig = {
isFirstLaunch: true,
init: false,
themeMode: 'system',
themeColor: 'blue',
selectedGitMirror: 'github',
selectedPythonMirror: 'tsinghua',
selectedPipMirror: 'tsinghua',
pythonInstalled: false,
gitInstalled: false,
backendExists: false,
dependenciesInstalled: false,
pipInstalled: false
}
// 读取配置(内部使用,不触发保存)
async function getConfigInternal(): Promise<FrontendConfig> {
try {
// 优先从文件读取配置
const fileConfig = await window.electronAPI.loadConfig()
if (fileConfig) {
console.log('从文件加载配置:', fileConfig)
return { ...DEFAULT_CONFIG, ...fileConfig }
}
// 如果文件不存在尝试从localStorage迁移
const localConfig = localStorage.getItem('app-config')
const themeConfig = localStorage.getItem('theme-settings')
let config = { ...DEFAULT_CONFIG }
if (localConfig) {
const parsed = JSON.parse(localConfig)
config = { ...config, ...parsed }
console.log('从localStorage迁移配置:', parsed)
}
if (themeConfig) {
const parsed = JSON.parse(themeConfig)
config.themeMode = parsed.themeMode || 'system'
config.themeColor = parsed.themeColor || 'blue'
console.log('从localStorage迁移主题配置:', parsed)
}
return config
} catch (error) {
console.error('读取配置失败:', error)
logger.error('读取配置失败', error)
return { ...DEFAULT_CONFIG }
}
}
// 读取配置(公共接口)
export async function getConfig(): Promise<FrontendConfig> {
const config = await getConfigInternal()
// 如果是从localStorage迁移的配置保存到文件并清理localStorage
const hasLocalStorage = localStorage.getItem('app-config') || localStorage.getItem('theme-settings')
if (hasLocalStorage) {
try {
await window.electronAPI.saveConfig(config)
localStorage.removeItem('app-config')
localStorage.removeItem('theme-settings')
localStorage.removeItem('app-initialized')
console.log('配置已从localStorage迁移到文件')
} catch (error) {
console.error('迁移配置失败:', error)
}
}
return config
}
// 保存配置
export async function saveConfig(config: Partial<FrontendConfig>): Promise<void> {
try {
console.log('开始保存配置:', config)
const currentConfig = await getConfigInternal() // 使用内部函数避免递归
const newConfig = { ...currentConfig, ...config }
console.log('合并后的配置:', newConfig)
await window.electronAPI.saveConfig(newConfig)
console.log('配置保存成功')
logger.info('配置已保存', newConfig)
} catch (error) {
console.error('保存配置失败:', error)
logger.error('保存配置失败', error)
throw error
}
}
// 重置配置
export async function resetConfig(): Promise<void> {
try {
await window.electronAPI.resetConfig()
localStorage.removeItem('app-config')
localStorage.removeItem('theme-settings')
localStorage.removeItem('app-initialized')
logger.info('配置已重置')
} catch (error) {
logger.error('重置配置失败', error)
}
}
// 检查是否已初始化
export async function isAppInitialized(): Promise<boolean> {
const config = await getConfig()
console.log('isAppInitialized 检查配置:', config)
console.log('init 字段值:', config.init)
console.log('init === true:', config.init === true)
return config.init === true
}
// 检查是否第一次启动
export async function isFirstLaunch(): Promise<boolean> {
const config = await getConfig()
return config.isFirstLaunch === true
}
// 设置初始化完成
export async function setInitialized(value: boolean = true): Promise<void> {
await saveConfig({ init: value, isFirstLaunch: false })
}
// 保存主题设置
export async function saveThemeConfig(themeMode: ThemeMode, themeColor: ThemeColor): Promise<void> {
await saveConfig({ themeMode, themeColor })
}
// 保存镜像源设置
export async function saveMirrorConfig(gitMirror: string, pythonMirror?: string, pipMirror?: string): Promise<void> {
const config: Partial<FrontendConfig> = { selectedGitMirror: gitMirror }
if (pythonMirror) config.selectedPythonMirror = pythonMirror
if (pipMirror) config.selectedPipMirror = pipMirror
await saveConfig(config)
}