feat: Implement initial full-stack application structure including frontend pages, components, hooks, API integration, and backend services for account pooling and management.
This commit is contained in:
107
frontend/src/utils/storage.ts
Normal file
107
frontend/src/utils/storage.ts
Normal file
@@ -0,0 +1,107 @@
|
||||
import type { AppConfig, AddRecord } from '../types'
|
||||
import { defaultConfig } from '../types'
|
||||
|
||||
const STORAGE_KEYS = {
|
||||
CONFIG: 'codex-pool-config',
|
||||
RECORDS: 'codex-pool-records',
|
||||
} as const
|
||||
|
||||
/**
|
||||
* 保存配置到 localStorage
|
||||
*/
|
||||
export function saveConfig(config: AppConfig): void {
|
||||
try {
|
||||
localStorage.setItem(STORAGE_KEYS.CONFIG, JSON.stringify(config))
|
||||
} catch (error) {
|
||||
console.error('Failed to save config:', error)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 从 localStorage 加载配置
|
||||
*/
|
||||
export function loadConfig(): AppConfig {
|
||||
try {
|
||||
const stored = localStorage.getItem(STORAGE_KEYS.CONFIG)
|
||||
if (stored) {
|
||||
const parsed = JSON.parse(stored)
|
||||
|
||||
// Migration: handle old email config format -> new services array format
|
||||
let emailConfig = { ...defaultConfig.email }
|
||||
|
||||
if (parsed.email) {
|
||||
if (parsed.email.services && Array.isArray(parsed.email.services)) {
|
||||
// New format - use directly
|
||||
emailConfig.services = parsed.email.services
|
||||
} else if (parsed.email.apiBase || parsed.email.domains) {
|
||||
// Old format - migrate to new services array
|
||||
const domains = parsed.email.domains || (parsed.email.domain ? [parsed.email.domain] : ['esyteam.edu.kg'])
|
||||
emailConfig.services = [{
|
||||
name: 'default',
|
||||
apiBase: parsed.email.apiBase || 'https://mail.esyteam.edu.kg',
|
||||
apiToken: parsed.email.apiToken || '',
|
||||
domain: domains[0] || 'esyteam.edu.kg',
|
||||
}]
|
||||
}
|
||||
}
|
||||
|
||||
// 合并默认配置,确保新增字段有默认值
|
||||
return {
|
||||
...defaultConfig,
|
||||
...parsed,
|
||||
s2a: { ...defaultConfig.s2a, ...parsed.s2a },
|
||||
pooling: { ...defaultConfig.pooling, ...parsed.pooling },
|
||||
check: { ...defaultConfig.check, ...parsed.check },
|
||||
email: emailConfig,
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to load config:', error)
|
||||
}
|
||||
return defaultConfig
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存记录到 localStorage
|
||||
*/
|
||||
export function saveRecords(records: AddRecord[]): void {
|
||||
try {
|
||||
localStorage.setItem(STORAGE_KEYS.RECORDS, JSON.stringify(records))
|
||||
} catch (error) {
|
||||
console.error('Failed to save records:', error)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 从 localStorage 加载记录
|
||||
*/
|
||||
export function loadRecords(): AddRecord[] {
|
||||
try {
|
||||
const stored = localStorage.getItem(STORAGE_KEYS.RECORDS)
|
||||
if (stored) {
|
||||
return JSON.parse(stored)
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to load records:', error)
|
||||
}
|
||||
return []
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成唯一 ID
|
||||
*/
|
||||
export function generateId(): string {
|
||||
return `${Date.now()}-${Math.random().toString(36).substring(2, 9)}`
|
||||
}
|
||||
|
||||
/**
|
||||
* 清除所有存储数据
|
||||
*/
|
||||
export function clearStorage(): void {
|
||||
try {
|
||||
localStorage.removeItem(STORAGE_KEYS.CONFIG)
|
||||
localStorage.removeItem(STORAGE_KEYS.RECORDS)
|
||||
} catch (error) {
|
||||
console.error('Failed to clear storage:', error)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user