feat: add recipe translation tool with AI translation and settings management

- Add Word document parsing and translation export
- Add database configuration management
- Add AI/LLM translation configuration
- Add translation vocabulary management
- Add export settings (colors, page orientation, headers)
- Separate database and AI configurations
- Add debounced search to prevent database overload
This commit is contained in:
2026-04-12 23:50:54 +08:00
parent 57e119635e
commit a249fb038c
24 changed files with 3383 additions and 70 deletions
+173
View File
@@ -0,0 +1,173 @@
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 AppConfig {
db: DBConfig;
ai: AIConfig;
}
// 配置文件路径(单一文件)
const configPath = path.join(process.cwd(), "config.json");
/**
* 读取完整配置
*/
function readConfigFile(): Partial<AppConfig> {
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 };
}
/**
* 获取完整配置(兼容旧接口)
*/
export function getConfig(): AppConfig {
return {
db: getDBConfig(),
ai: getAIConfig(),
};
}
/**
* 保存数据库配置
*/
export function saveDBConfig(config: Partial<DBConfig>): 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" },
db: newConfig,
};
writeConfigFile(updatedConfig);
return newConfig;
}
/**
* 保存AI翻译配置
*/
export function saveAIConfig(config: Partial<AIConfig>): 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" },
ai: newConfig,
};
writeConfigFile(updatedConfig);
return newConfig;
}
/**
* 保存完整配置(兼容旧接口)
*/
export function saveConfig(config: Partial<AppConfig>): AppConfig {
const current = getConfig();
const fileConfig = readConfigFile();
return {
db: config.db ? saveDBConfig(config.db) : current.db,
ai: config.ai ? saveAIConfig(config.ai) : current.ai,
};
}