You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

294 lines
7.7 KiB
JavaScript

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

const sqlite3 = require("sqlite3").verbose();
const path = require("path");
const { app } = require("electron");
const { spawn, exec } = require("child_process");
// 进程引用管理
const processes = {
LiveTalkingProcess: null,
gptsovitsProcess: null,
chatProcess: null
};
// 获取数据库路径
function getDatabasePath() {
if (process.env.NODE_ENV === "development") {
const dbPath = path.join(__dirname, "..", "..", "live_chat.db");
return dbPath;
} else {
const exePath = app.getPath("exe");
// 获取win-unpacked文件夹路径
const winUnpackedDir = path.dirname(exePath);
// 获取win-unpacked的上级目录与win-unpacked同级的目录
const parentDir = path.dirname(winUnpackedDir);
// 构建live_chat.db的完整路径
const dbPath = path.join(parentDir, "live_chat.db");
console.log("dbPath", dbPath);
return dbPath;
}
}
// 更新配置值
function updateConfig(tableName, key, value) {
return new Promise((resolve, reject) => {
const db = new sqlite3.Database(getDatabasePath(), err => {
if (err) {
console.error("数据库连接错误:", err.message);
return reject(err);
}
});
// 先尝试更新如果影响行数为0则插入新记录
db.run(
`UPDATE ${tableName} SET value = ? WHERE key = ?`,
[value, key],
function (err) {
if (err) {
db.close();
return reject(err);
}
// 如果没有匹配的记录则插入
if (this.changes === 0) {
db.run(
`INSERT INTO ${tableName} (key, value) VALUES (?, ?)`,
[key, value],
function (err) {
db.close();
if (err) return reject(err);
resolve({
success: true,
action: "insert",
changes: this.changes
});
}
);
} else {
db.close();
resolve({ success: true, action: "update", changes: this.changes });
}
}
);
});
}
// 获取配置值
function getConfigValue(tableName, key) {
return new Promise((resolve, reject) => {
const db = new sqlite3.Database(getDatabasePath(), err => {
if (err) {
return reject(err);
}
});
db.get(
`SELECT value FROM ${tableName} WHERE key = ?`,
[key],
(err, row) => {
db.close();
if (err) return reject(err);
resolve(row ? row.value : null);
}
);
});
}
// 批量插入系统消息
const bulkInsertSystemMessages = messages => {
console.log("系统消息:", messages);
return new Promise((resolve, reject) => {
if (!Array.isArray(messages) || messages.length === 0) {
reject(new Error("请提供有效的消息数组"));
return;
}
try {
const db = new sqlite3.Database(getDatabasePath(), err => {
if (err) {
reject(err);
return;
}
// 使用事务进行批量插入,提高性能
db.run("BEGIN TRANSACTION", err => {
if (err) {
reject(err);
db.close();
return;
}
const stmt = db.prepare(
"INSERT INTO system_message (message) VALUES (?)"
);
let completed = 0;
let errorOccurred = null;
messages.forEach(message => {
stmt.run(message, function (err) {
if (err && !errorOccurred) {
errorOccurred = err;
}
completed++;
// 所有消息都处理完毕
if (completed === messages.length) {
stmt.finalize();
if (errorOccurred) {
db.run("ROLLBACK", () => {
reject(errorOccurred);
db.close();
});
} else {
db.run("COMMIT", err => {
if (err) {
reject(err);
} else {
resolve({
success: true,
count: messages.length
});
}
db.close();
});
}
}
});
});
});
});
} catch (error) {
reject(error);
}
});
};
// 清空系统消息表
const clearSystemMessages = () => {
return new Promise((resolve, reject) => {
const db = new sqlite3.Database(getDatabasePath(), err => {
if (err) {
reject(err);
return;
}
// 使用TRUNCATE-like操作清空表同时重置自增ID
db.run("DELETE FROM system_message", err => {
if (err) {
reject(err);
db.close();
return;
}
// 重置自增计数器SQLite特定
db.run(
"DELETE FROM sqlite_sequence WHERE name = 'system_message'",
err => {
if (err) {
reject(err);
} else {
resolve({ success: true });
}
db.close();
}
);
});
});
});
};
function getProcessExePath(fileName, exeName) {
let exePath;
let exeFolder;
// 判断是否为开发环境
if (process.env.NODE_ENV === "development") {
// process.cwd() 通常指向项目根目录
const projectRoot = process.cwd();
const parentDir = path.dirname(projectRoot);
exePath = path.join(parentDir, fileName, exeName);
exeFolder = path.join(parentDir, fileName);
} else {
// 生产环境: 与win-unpacked同级目录下的LiveTalking文件夹
exePath = app.getPath("exe");
// 获取win-unpacked文件夹路径
const winUnpackedDir = path.dirname(exePath);
// 获取win-unpacked的上级目录
const parentDir = path.dirname(winUnpackedDir);
exePath = path.join(parentDir, fileName, exeName);
exeFolder = path.join(parentDir, fileName);
}
console.log("exePath", exePath);
console.log("exeFolder", exeFolder);
// 标准化路径格式
return { exePath, exeFolder };
}
/**
* 启动LiveTalking.exe
*/
async function startProcess(fileName, exeName) {
return new Promise(async (resolve, reject) => {
const processKey = `${fileName}Process`;
if (processes[processKey]) {
reject(`${fileName} is already running`);
return;
}
// 获取程序路径
const obj = getProcessExePath(fileName, exeName);
try {
// 启动进程时通过wmic获取详细信息仅Windows
const newProcess = spawn("cmd.exe", ["/c", obj.exePath], {
// 直接运行bat不使用start命令
cwd: obj.exeFolder,
windowsVerbatimArguments: true,
windowsHide: false,
detached: false // 不分离,便于跟踪子进程
});
// 记录进程ID关键保存实际PID
processes[processKey] = {
process: newProcess,
pid: newProcess.pid // 保存PID用于后续终止
};
newProcess.on("error", err => {
processes[processKey] = null;
reject(`启动失败: ${err.message}`);
});
console.log(`spawned with PID ${newProcess.pid}`);
resolve(`${fileName} 启动成功 (PID: ${newProcess.pid})`);
} catch (err) {
reject(`启动异常: ${err.message}`);
}
});
}
// 停止所有进程
async function stopAllProcesses() {
try {
// 清空所有属性,变成空对象
for (const key in processes) {
if (processes[key]) {
delete processes[key];
}
}
const projectRoot = process.cwd();
const parentDir = path.dirname(projectRoot);
const exPath = path.join(parentDir, "kill-live.bat");
const child = spawn("cmd.exe", ["/c", "start", '""', `"${exPath}"`], {
cwd: parentDir,
windowsVerbatimArguments: true,
windowsHide: false,
detached: true
});
child.unref();
} catch (err) {
console.error(err);
}
}
module.exports = {
updateConfig,
getConfigValue,
bulkInsertSystemMessages,
clearSystemMessages,
startProcess,
stopAllProcesses
};