import fs from "fs"; import path from "path"; export interface DBConfig { host: string; port: number; user: string; password: string; database: string; } export interface AIConfig { apiKey: string; baseUrl: string; model: string; } export interface ExportConfig { // 未翻译文本的颜色 (hex) untranslatedColor: string; // 第二页是否显示表头 secondPageHeader: boolean; // 页面方向: portrait | landscape orientation: "portrait" | "landscape"; } export interface AppConfig { db: DBConfig; ai: AIConfig; export: ExportConfig; } // 配置文件路径(单一文件) const configPath = path.join(process.cwd(), "config.json"); /** * 读取完整配置 */ function readConfigFile(): Partial { try { if (fs.existsSync(configPath)) { const content = fs.readFileSync(configPath, "utf-8"); return JSON.parse(content); } } catch (e) { console.error("Config read error:", e); } return {}; } /** * 写入完整配置 */ function writeConfigFile(config: AppConfig): void { fs.writeFileSync(configPath, JSON.stringify(config, null, 2), "utf-8"); } /** * 获取数据库配置 * 优先级:环境变量 > config.json */ export function getDBConfig(): DBConfig { let host = "127.0.0.1"; let port = 3306; let user = "root"; let password = ""; let database = "recipe_tools"; // 环境变量优先级最高 if (process.env.DB_HOST) host = process.env.DB_HOST; if (process.env.DB_PORT) port = parseInt(process.env.DB_PORT); if (process.env.DB_USER) user = process.env.DB_USER; if (process.env.DB_PASSWORD) password = process.env.DB_PASSWORD; if (process.env.DB_NAME) database = process.env.DB_NAME; // config.json 次之(仅当环境变量未设置时) const fileConfig = readConfigFile(); if (fileConfig.db) { if (fileConfig.db.host && !process.env.DB_HOST) host = fileConfig.db.host; if (fileConfig.db.port && !process.env.DB_PORT) port = fileConfig.db.port; if (fileConfig.db.user && !process.env.DB_USER) user = fileConfig.db.user; if (fileConfig.db.password && !process.env.DB_PASSWORD) password = fileConfig.db.password; if (fileConfig.db.database && !process.env.DB_NAME) database = fileConfig.db.database; } return { host, port, user, password, database }; } /** * 获取AI翻译配置 * 优先级:环境变量 > config.json */ export function getAIConfig(): AIConfig { let apiKey = ""; let baseUrl = "https://api.openai.com/v1"; let model = "gpt-3.5-turbo"; // 环境变量优先级最高 if (process.env.AI_API_KEY) apiKey = process.env.AI_API_KEY; if (process.env.AI_BASE_URL) baseUrl = process.env.AI_BASE_URL; if (process.env.AI_MODEL) model = process.env.AI_MODEL; // config.json 次之(仅当环境变量未设置时) const fileConfig = readConfigFile(); if (fileConfig.ai) { if (fileConfig.ai.apiKey && !process.env.AI_API_KEY) apiKey = fileConfig.ai.apiKey; if (fileConfig.ai.baseUrl && !process.env.AI_BASE_URL) baseUrl = fileConfig.ai.baseUrl; if (fileConfig.ai.model && !process.env.AI_MODEL) model = fileConfig.ai.model; } return { apiKey, baseUrl, model }; } /** * 获取导出配置 * 优先级:config.json(没有环境变量) */ export function getExportConfig(): ExportConfig { const defaultConfig: ExportConfig = { untranslatedColor: "CC0000", secondPageHeader: false, orientation: "landscape", }; const fileConfig = readConfigFile(); if (fileConfig.export) { return { untranslatedColor: fileConfig.export.untranslatedColor || defaultConfig.untranslatedColor, secondPageHeader: fileConfig.export.secondPageHeader ?? defaultConfig.secondPageHeader, orientation: fileConfig.export.orientation || defaultConfig.orientation, }; } return defaultConfig; } /** * 获取完整配置(兼容旧接口) */ export function getConfig(): AppConfig { return { db: getDBConfig(), ai: getAIConfig(), export: getExportConfig(), }; } /** * 保存数据库配置 */ export function saveDBConfig(config: Partial): DBConfig { const current = getDBConfig(); const newConfig: DBConfig = { host: config.host ?? current.host, port: config.port ?? current.port, user: config.user ?? current.user, password: config.password ?? current.password, database: config.database ?? current.database, }; // 读取现有配置,更新 db 部分 const fileConfig = readConfigFile(); const updatedConfig: AppConfig = { ai: fileConfig.ai ?? { apiKey: "", baseUrl: "https://api.openai.com/v1", model: "gpt-3.5-turbo" }, export: fileConfig.export ?? { untranslatedColor: "CC0000", secondPageHeader: false, orientation: "landscape" }, db: newConfig, }; writeConfigFile(updatedConfig); return newConfig; } /** * 保存AI翻译配置 */ export function saveAIConfig(config: Partial): AIConfig { const current = getAIConfig(); const newConfig: AIConfig = { apiKey: config.apiKey ?? current.apiKey, baseUrl: config.baseUrl ?? current.baseUrl, model: config.model ?? current.model, }; // 读取现有配置,更新 ai 部分 const fileConfig = readConfigFile(); const updatedConfig: AppConfig = { db: fileConfig.db ?? { host: "127.0.0.1", port: 3306, user: "root", password: "", database: "recipe_tools" }, export: fileConfig.export ?? { untranslatedColor: "CC0000", secondPageHeader: false, orientation: "landscape" }, ai: newConfig, }; writeConfigFile(updatedConfig); return newConfig; } /** * 保存导出配置 */ export function saveExportConfig(config: Partial): ExportConfig { const current = getExportConfig(); const newConfig: ExportConfig = { untranslatedColor: config.untranslatedColor ?? current.untranslatedColor, secondPageHeader: config.secondPageHeader ?? current.secondPageHeader, orientation: config.orientation ?? current.orientation, }; // 读取现有配置,更新 export 部分 const fileConfig = readConfigFile(); const updatedConfig: AppConfig = { db: fileConfig.db ?? { host: "127.0.0.1", port: 3306, user: "root", password: "", database: "recipe_tools" }, ai: fileConfig.ai ?? { apiKey: "", baseUrl: "https://api.openai.com/v1", model: "gpt-3.5-turbo" }, export: newConfig, }; writeConfigFile(updatedConfig); return newConfig; } /** * 保存完整配置(兼容旧接口) */ export function saveConfig(config: Partial): AppConfig { const current = getConfig(); const fileConfig = readConfigFile(); return { db: config.db ? saveDBConfig(config.db) : current.db, ai: config.ai ? saveAIConfig(config.ai) : current.ai, export: config.export ? saveExportConfig(config.export) : current.export, }; }