Files
dify_market_manager_gui/src/main/ipc.js
2026-02-02 19:08:26 +08:00

430 lines
13 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { BrowserWindow, ipcMain, shell, Notification, app } from "electron";
import { setStoreValue, getStoreValue } from './store.js'
import { createNewWindow, createWindow, getMainWindow, getDrageWindow, closeApiConfigWindow, closeConfigWindow } from './window.js'
import { difyRetryRequestTimer } from './dify.js'
import axios from 'axios'
import log from 'electron-log/main';
import fs from 'fs';
import os from 'os';
import path from 'path';
log.initialize();
import {checkForUpdates} from "./utils/updateUtils"
import logger from './utils/logger'
import dayjs from 'dayjs'
function isValidUrl(_url) {
const containsApp = _url.includes('/app/');
const containsConfigurationOrWorkflow = _url.includes('/configuration') || _url.includes('/workflow');
// 只有当 URL 包含 'app' 并且包含 'configuration' 或 'workflow' 时,才返回 true
return containsApp && containsConfigurationOrWorkflow;
}
export function setupIPC() {
ipcMain.handle('initClientData', (event, data) => {
logger.info('=======================================initClientData')
logger.info(data)
setStoreValue("h5_data", data);
setStoreValue("token", data.token);
setStoreValue("dify_access_token:", data.dify_access_token);
setStoreValue("dify_refresh_token", data.dify_refresh_token);
setStoreValue("dify_csrf_token", data.dify_csrf_token);
setStoreValue("userInfo", data.userInfo);
setStoreValue("apiUrl", data.apiUrl);
setStoreValue("difySite", data.difySite);
setStoreValue("lastAliveTime",dayjs())
difyRetryRequestTimer()
return 'pong'
})
ipcMain.handle('openNewWindow', (event, _url, dify_access_token, refresh_token) => {
logger.info('=======================================openNewWindow')
logger.info(_url)
const _sandbox=isValidUrl(_url)
logger.info('=======================================openNewWindow _sandbox:',_sandbox)
createNewWindow(_url, dify_access_token, refresh_token,_sandbox)
return 'pong'
})
ipcMain.handle('setMainWindowTitle', (event, title) => {
const mainWindow = getMainWindow();
if (mainWindow && !mainWindow.isDestroyed()) {
mainWindow.setTitle(title);
}
return 'pong'
})
ipcMain.handle('setLocalStorage', (event, key, value) => {
setStoreValue("token", data.token);
return 'pong'
})
ipcMain.handle('setGuiLocalStorage', (event, key, value) => {
logger.info("=============================================: setGuiLocalStorage key", key)
logger.info("=============================================: setGuiLocalStorage value", value)
setStoreValue(key, value);
return 'pong'
})
ipcMain.handle('getGuiLocalStorage', (event, key) => {
return getStoreValue(key)
})
ipcMain.handle('difyWebUploadFileToApi', async (event, datasetId, data) => {
logger.info("=============================================: difyWebUploadFileToApi");
logger.info("=============================================: datasetId: " + datasetId);
logger.info("=============================================: data: ");
logger.info(data)
try {
const java_api = getStoreValue("apiUrl") + "/bqw-ai" + "/app/api/knowledge/addDocumentToKnowledge";
const token = getStoreValue("token");
if (!java_api || !token) {
throw new Error("API URL or Token is missing in the store.");
}
const params = {
kg_id: datasetId,
files: datasetId,
knowledgeDocumentParams: JSON.parse(data)
};
logger.info("=======================java_api:"+java_api);
logger.info("=======================params:")
logger.info(params)
const response = await axios.post(java_api, params, {
headers: {
'x-access-token': `${token}`,
'Content-Type': 'application/json'
}
});
logger.info("Response from server:", response.data);
// 获取当前窗口并关闭
const currentWindow = event.sender.getOwnerBrowserWindow();
if (currentWindow && !currentWindow.isDestroyed()) {
currentWindow.close();
}
return response.data;
} catch (error) {
console.error("Error making POST request:", error.message);
throw error;
}
});
ipcMain.on('difyWebUpdateDatasetsInfo', (event) => {
return 'pong'
})
ipcMain.on('app:window:set-position', (event, x, y) => {
const drageWindow = getDrageWindow();
if (drageWindow) {
drageWindow.setPosition(x, y)
}
return 'pong'
})
ipcMain.handle('app:window:switch-show-main-window', (event) => {
const mainWindow = getMainWindow();
if (mainWindow && !mainWindow.isDestroyed()) {
if (mainWindow.isVisible()) {
mainWindow.hide();
} else {
mainWindow.show();
}
} else {
createWindow();
}
});
ipcMain.handle('app:window:get-position', (event) => {
const drageWindow = getDrageWindow();
if (drageWindow) {
const [x, y] = drageWindow.getPosition();
return { x, y }
}
return { x: 0, y: 0 }
})
// 获取存储值
ipcMain.handle('getStoreValue', (event, key) => {
return getStoreValue(key)
})
// 设置存储值
ipcMain.handle('setStoreValue', (event, key, value) => {
return setStoreValue(key, value)
})
// 设置存储值
ipcMain.handle('setStoreValueByConfig', (event, key, value) => {
return setStoreValue(key, value)
})
// 关闭配置窗口
ipcMain.on('closeApiConfigWindow', () => {
closeApiConfigWindow()
})
ipcMain.on('closeConfigWindow', () => {
closeConfigWindow()
})
// 添加新的 IPC 监听处理函数
ipcMain.handle('openNewPage', (event, url) => {
const newWindow = new BrowserWindow({
fullscreen: false,
width: 1200,
height: 700,
minWidth: 1200,
minHeight: 700,
webPreferences: {
webSecurity: false, // 禁用 Web 安全
nodeIntegration: true,
contextIsolation: false,
}
});
newWindow.loadURL(url);
// 添加重试机制的错误处理
let failLoadCount = 0;
const maxRetries = 2;
const retryDelay = 1000;
newWindow.webContents.on('did-fail-load', (event, errorCode, errorDescription) => {
console.error('页面加载失败:', errorDescription);
failLoadCount++;
if (failLoadCount <= maxRetries) {
console.log(`页面加载失败,${retryDelay}ms后进行第${failLoadCount}次重试...`);
setTimeout(() => {
newWindow.reload();
}, retryDelay);
} else {
console.error('页面加载失败次数超过最大重试次数');
}
});
// 页面加载成功时重置失败计数
newWindow.webContents.on('did-finish-load', () => {
if (failLoadCount > 0) {
console.log('页面加载成功,重置失败计数');
failLoadCount = 0;
}
});
return 'success';
});
// 添加新的 IPC 监听处理函数
ipcMain.handle('openCSDNAiPage', (event, url) => {
const newWindow = new BrowserWindow({
fullscreen: false,
width: 1600,
height: 900,
webPreferences: {
webSecurity: false, // 禁用 Web 安全
nodeIntegration: false,
contextIsolation: false,
}
});
newWindow.loadURL(url);
// 添加重试机制的错误处理
let failLoadCount2 = 0;
const maxRetries2 = 2;
const retryDelay2 = 1000;
newWindow.webContents.on('did-fail-load', (event, errorCode, errorDescription) => {
console.error('页面加载失败:', errorDescription);
failLoadCount2++;
if (failLoadCount2 <= maxRetries2) {
console.log(`页面加载失败,${retryDelay2}ms后进行第${failLoadCount2}次重试...`);
setTimeout(() => {
newWindow.reload();
}, retryDelay2);
} else {
console.error('页面加载失败次数超过最大重试次数');
}
});
// 页面加载成功时重置失败计数
newWindow.webContents.on('did-finish-load', () => {
if (failLoadCount2 > 0) {
console.log('页面加载成功,重置失败计数');
failLoadCount2 = 0;
}
});
return 'success';
});
ipcMain.handle('openNewPagebySystemBrowser', (event, url) => {
shell.openExternal(url);
return 'success';
});
// 添加新的 IPC 监听处理函数
ipcMain.handle('updateToNewVersion', async (event) => {
checkForUpdates({},false)
});
// 下载文件并打开下载目录
ipcMain.handle('downloadFile', async (event, fileUrl) => {
logger.info("=============================开始下载文件:",fileUrl)
try {
// 解码URL
fileUrl = decodeURI(fileUrl);
// 简单提取文件名从URL路径的最后一部分获取
let fileName = '';
try {
const url = new URL(fileUrl);
const pathSegments = url.pathname.split('/').filter(segment => segment);
fileName = pathSegments[pathSegments.length - 1] || '';
} catch (error) {
// 如果URL解析失败尝试直接从字符串中提取
const urlParts = fileUrl.split('/');
fileName = urlParts[urlParts.length - 1] || '';
}
// 解码文件名,解决中文乱码问题
try {
fileName = decodeURIComponent(fileName);
} catch (error) {
// 如果解码失败,保持原文件名
logger.warn(`文件名解码失败: ${fileName}`);
}
// 如果提取的文件名为空,使用时间戳生成默认名称
if (!fileName || fileName === '') {
fileName = `downloaded_file_${Date.now()}`;
}
// 获取用户下载目录
const downloadDir = path.join(os.homedir(), 'Downloads');
// 确保下载目录存在
if (!fs.existsSync(downloadDir)) {
fs.mkdirSync(downloadDir, { recursive: true });
}
const outputLocationPath = path.join(downloadDir, fileName);
const writer = fs.createWriteStream(outputLocationPath);
let receivedBytes = 0;
logger.info(`开始下载文件: ${fileUrl}`);
logger.info(`提取的文件名: ${fileName}`);
logger.info(`保存路径: ${outputLocationPath}`);
const downloadResponse = await axios({
method: "get",
url: fileUrl,
responseType: "stream"
});
const totalBytes = downloadResponse.headers["content-length"];
downloadResponse.data.on("data", (chunk) => {
receivedBytes += chunk.length;
if (totalBytes) {
let progress = Math.floor((receivedBytes / totalBytes) * 100);
// 发送进度给渲染进程
event.sender.send("download-progress", progress);
}
});
downloadResponse.data.pipe(writer);
return new Promise((resolve, reject) => {
writer.on("finish", async () => {
logger.info(`文件下载完成: ${outputLocationPath}`);
try {
// 打开文件所在目录
await shell.showItemInFolder(outputLocationPath);
resolve({ success: true, filePath: outputLocationPath, fileName: fileName });
} catch (error) {
logger.error(`打开目录失败: ${error.message}`);
reject(error);
}
});
writer.on("error", (error) => {
logger.error(`文件写入失败: ${error.message}`);
reject(error);
});
});
} catch (error) {
logger.error(`下载文件失败: ${error.message}`);
throw error;
}
});
// 重启软件
ipcMain.handle('restartApp', async (event) => {
logger.info("=============================重启软件");
try {
// 标记为正在重启,避免其他退出逻辑干扰
app.isRestarting = true;
// 确保所有窗口都被正确关闭
const windows = BrowserWindow.getAllWindows();
logger.info(`准备关闭 ${windows.length} 个窗口`);
windows.forEach(window => {
if (!window.isDestroyed()) {
try {
window.close();
logger.info('窗口关闭成功');
} catch (error) {
logger.warn('关闭窗口时出错:', error);
}
}
});
// 延迟执行重启,确保窗口关闭完成
setTimeout(() => {
try {
logger.info('执行应用重启');
app.relaunch();
app.exit(0);
} catch (error) {
logger.error('重启应用失败,尝试强制退出:', error);
try {
app.quit();
} catch (quitError) {
logger.error('强制退出也失败:', quitError);
process.exit(0);
}
}
}, 1000);
return { success: true };
} catch (error) {
logger.error(`重启软件失败: ${error.message}`);
throw error;
}
});
}