Compare commits

...

2 Commits

Author SHA1 Message Date
9f2bf83a50 移除依赖 2026-02-09 15:03:04 +08:00
b3d77ba14d 升级适配 2026-02-02 19:08:26 +08:00
4 changed files with 184 additions and 39 deletions

View File

@@ -1,2 +1,2 @@
VITE_h5_client_url=http://10.101.27.243:18900 VITE_h5_client_url=http://10.102.9.139:18901
VITE_HsAppCode=1 VITE_HsAppCode=1

View File

@@ -24,6 +24,7 @@
"build:win_11_120": "electron-vite build --mode 11_120 && electron-builder --win ", "build:win_11_120": "electron-vite build --mode 11_120 && electron-builder --win ",
"build:win_13_27": "electron-vite build --mode 13_27 && electron-builder --win ", "build:win_13_27": "electron-vite build --mode 13_27 && electron-builder --win ",
"build:win_lgzs": "electron-vite build --mode lgzs && electron-builder --win ", "build:win_lgzs": "electron-vite build --mode lgzs && electron-builder --win ",
"build:win_lgzs_test": "electron-vite build --mode lgzs_test && electron-builder --win ",
"build:win_jiangsu": "electron-vite build --mode jiangsu && electron-builder --win ", "build:win_jiangsu": "electron-vite build --mode jiangsu && electron-builder --win ",
"build:win_nanshan": "electron-vite build --mode nanshan && electron-builder --win", "build:win_nanshan": "electron-vite build --mode nanshan && electron-builder --win",
"build:win_huashiai": "electron-vite build --mode huashiai && electron-builder --win", "build:win_huashiai": "electron-vite build --mode huashiai && electron-builder --win",
@@ -52,8 +53,6 @@
"xe-utils": "^3.7.4" "xe-utils": "^3.7.4"
}, },
"devDependencies": { "devDependencies": {
"@electron-forge/cli": "^6.2.1",
"@electron-forge/maker-deb": "^6.2.1",
"@electron-toolkit/eslint-config": "^2.0.0", "@electron-toolkit/eslint-config": "^2.0.0",
"@electron-toolkit/eslint-config-prettier": "^3.0.0", "@electron-toolkit/eslint-config-prettier": "^3.0.0",
"@vitejs/plugin-vue": "^5.2.1", "@vitejs/plugin-vue": "^5.2.1",

View File

@@ -25,9 +25,11 @@ export function setupIPC() {
logger.info('=======================================initClientData') logger.info('=======================================initClientData')
logger.info(data) logger.info(data)
setStoreValue("h5_data", data);
setStoreValue("token", data.token); setStoreValue("token", data.token);
setStoreValue("dify_access_token:", data.dify_access_token); setStoreValue("dify_access_token:", data.dify_access_token);
setStoreValue("dify_refresh_token", data.dify_refresh_token); setStoreValue("dify_refresh_token", data.dify_refresh_token);
setStoreValue("dify_csrf_token", data.dify_csrf_token);
setStoreValue("userInfo", data.userInfo); setStoreValue("userInfo", data.userInfo);
setStoreValue("apiUrl", data.apiUrl); setStoreValue("apiUrl", data.apiUrl);
@@ -207,7 +209,7 @@ export function setupIPC() {
newWindow.webContents.on('did-fail-load', (event, errorCode, errorDescription) => { newWindow.webContents.on('did-fail-load', (event, errorCode, errorDescription) => {
console.error('页面加载失败:', errorDescription); console.error('页面加载失败:', errorDescription);
failLoadCount++; failLoadCount++;
if (failLoadCount <= maxRetries) { if (failLoadCount <= maxRetries) {
console.log(`页面加载失败,${retryDelay}ms后进行第${failLoadCount}次重试...`); console.log(`页面加载失败,${retryDelay}ms后进行第${failLoadCount}次重试...`);
setTimeout(() => { setTimeout(() => {
@@ -252,7 +254,7 @@ export function setupIPC() {
newWindow.webContents.on('did-fail-load', (event, errorCode, errorDescription) => { newWindow.webContents.on('did-fail-load', (event, errorCode, errorDescription) => {
console.error('页面加载失败:', errorDescription); console.error('页面加载失败:', errorDescription);
failLoadCount2++; failLoadCount2++;
if (failLoadCount2 <= maxRetries2) { if (failLoadCount2 <= maxRetries2) {
console.log(`页面加载失败,${retryDelay2}ms后进行第${failLoadCount2}次重试...`); console.log(`页面加载失败,${retryDelay2}ms后进行第${failLoadCount2}次重试...`);
setTimeout(() => { setTimeout(() => {
@@ -307,7 +309,7 @@ export function setupIPC() {
const urlParts = fileUrl.split('/'); const urlParts = fileUrl.split('/');
fileName = urlParts[urlParts.length - 1] || ''; fileName = urlParts[urlParts.length - 1] || '';
} }
// 解码文件名,解决中文乱码问题 // 解码文件名,解决中文乱码问题
try { try {
fileName = decodeURIComponent(fileName); fileName = decodeURIComponent(fileName);
@@ -315,7 +317,7 @@ export function setupIPC() {
// 如果解码失败,保持原文件名 // 如果解码失败,保持原文件名
logger.warn(`文件名解码失败: ${fileName}`); logger.warn(`文件名解码失败: ${fileName}`);
} }
// 如果提取的文件名为空,使用时间戳生成默认名称 // 如果提取的文件名为空,使用时间戳生成默认名称
if (!fileName || fileName === '') { if (!fileName || fileName === '') {
fileName = `downloaded_file_${Date.now()}`; fileName = `downloaded_file_${Date.now()}`;
@@ -323,12 +325,12 @@ export function setupIPC() {
// 获取用户下载目录 // 获取用户下载目录
const downloadDir = path.join(os.homedir(), 'Downloads'); const downloadDir = path.join(os.homedir(), 'Downloads');
// 确保下载目录存在 // 确保下载目录存在
if (!fs.existsSync(downloadDir)) { if (!fs.existsSync(downloadDir)) {
fs.mkdirSync(downloadDir, { recursive: true }); fs.mkdirSync(downloadDir, { recursive: true });
} }
const outputLocationPath = path.join(downloadDir, fileName); const outputLocationPath = path.join(downloadDir, fileName);
const writer = fs.createWriteStream(outputLocationPath); const writer = fs.createWriteStream(outputLocationPath);
let receivedBytes = 0; let receivedBytes = 0;
@@ -385,11 +387,11 @@ export function setupIPC() {
try { try {
// 标记为正在重启,避免其他退出逻辑干扰 // 标记为正在重启,避免其他退出逻辑干扰
app.isRestarting = true; app.isRestarting = true;
// 确保所有窗口都被正确关闭 // 确保所有窗口都被正确关闭
const windows = BrowserWindow.getAllWindows(); const windows = BrowserWindow.getAllWindows();
logger.info(`准备关闭 ${windows.length} 个窗口`); logger.info(`准备关闭 ${windows.length} 个窗口`);
windows.forEach(window => { windows.forEach(window => {
if (!window.isDestroyed()) { if (!window.isDestroyed()) {
try { try {
@@ -400,7 +402,7 @@ export function setupIPC() {
} }
} }
}); });
// 延迟执行重启,确保窗口关闭完成 // 延迟执行重启,确保窗口关闭完成
setTimeout(() => { setTimeout(() => {
try { try {
@@ -417,7 +419,7 @@ export function setupIPC() {
} }
} }
}, 1000); }, 1000);
return { success: true }; return { success: true };
} catch (error) { } catch (error) {
logger.error(`重启软件失败: ${error.message}`); logger.error(`重启软件失败: ${error.message}`);

View File

@@ -17,6 +17,8 @@ let difyfullScreenWindow = null
let drageWindow = null let drageWindow = null
let apiConfigWindow = null let apiConfigWindow = null
let configWindow = null let configWindow = null
let cookieLogTimer = null
import { clearAllSessionData } from './utils/cacheUtils.js' import { clearAllSessionData } from './utils/cacheUtils.js'
// 权限授权 // 权限授权
async function checkMediaAccess(mediaType){ async function checkMediaAccess(mediaType){
@@ -85,7 +87,18 @@ export async function createWindow() {
// 创建菜单 // 创建菜单
createMenu(mainWindow, difyfullScreenWindow) createMenu(mainWindow, difyfullScreenWindow)
let code = `localStorage.setItem("IsHsAiApp","IsHsAiApp");localStorage.setItem("HsAppCode",${import.meta.env.VITE_HsAppCode});`
const isDebugger=getStoreValue("isDebugger");
const localStorageStatements = [
`localStorage.setItem("IsHsAiApp","IsHsAiApp");`,
`localStorage.setItem("HsAppCode",${import.meta.env.VITE_HsAppCode});`,
`localStorage.setItem("isDebugger",${isDebugger});`
].join('\n');
let code = `${localStorageStatements};`;
const isAdmin = getStoreValue("isAdmin") const isAdmin = getStoreValue("isAdmin")
@@ -107,12 +120,17 @@ export async function createWindow() {
// 监听快捷键 F12 来打开/关闭 DevTools // 监听快捷键 F12 来打开/关闭 DevTools
mainWindow.webContents.on('before-input-event', (event, input) => { mainWindow.webContents.on('before-input-event', (event, input) => {
if (input.key === 'F12') {
mainWindow.webContents.toggleDevTools() const isDebugger=getStoreValue("isDebugger");
} else if (input.key === 'F5') { if (isDebugger==1){
logger.info('主窗口 F5 快捷键触发') if (input.key === 'F12') {
mainWindow.reload() mainWindow.webContents.toggleDevTools()
} else if (input.key === 'F5') {
logger.info('全屏窗口 F5 快捷键触发')
mainWindow.reload()
}
} }
}) })
@@ -174,10 +192,10 @@ export async function createWindow() {
mainWindow.webContents.on('did-fail-load', async (event, errorCode, errorDescription, validatedURL) => { mainWindow.webContents.on('did-fail-load', async (event, errorCode, errorDescription, validatedURL) => {
logger.error(`主窗口页面加载失败: code=${errorCode}, desc=${errorDescription}, url=${validatedURL}, 失败次数: ${failLoadCount + 1}`) logger.error(`主窗口页面加载失败: code=${errorCode}, desc=${errorDescription}, url=${validatedURL}, 失败次数: ${failLoadCount + 1}`)
// 增加失败计数 // 增加失败计数
failLoadCount++; failLoadCount++;
if (failLoadCount <= maxRetries) { if (failLoadCount <= maxRetries) {
logger.info(`页面加载失败,${retryDelay}ms后进行第${failLoadCount}次重试...`); logger.info(`页面加载失败,${retryDelay}ms后进行第${failLoadCount}次重试...`);
setTimeout(async () => { setTimeout(async () => {
@@ -291,19 +309,30 @@ function registerShortcuts(window=null) {
logger.info(`F5快捷键注册${success ? '成功' : '失败'}`) logger.info(`F5快捷键注册${success ? '成功' : '失败'}`)
const isRegistered_F12 = globalShortcut.isRegistered('F12');
logger.info(`Is F12 registered: ${isRegistered_F12}`);
const isDebugger=getStoreValue("isDebugger");
if (isDebugger==1){
const isRegistered_F12 = globalShortcut.isRegistered('F12');
logger.info(`Is F12 registered: ${isRegistered_F12}`);
}
// 桌面端快要退出的时候,注销快捷键 // 桌面端快要退出的时候,注销快捷键
app.on('will-quit', () => { app.on('will-quit', () => {
globalShortcut.unregisterAll() // 注销所有快捷键 globalShortcut.unregisterAll() // 注销所有快捷键
}) })
} }
export async function createNewWindow(url, access_token, refresh_token,sandbox=false) { export async function createNewWindow(url, access_token, refresh_token,sandbox=false) {
const origin_url = url const origin_url = url
logger.info('==========createNewWindow') logger.info('==========createNewWindow')
logger.info('==========createNewWindow sandbox',sandbox) logger.info('==========createNewWindow sandbox',sandbox)
const csrf_token=getStoreValue("dify_csrf_token")
await checkAndApplyDeviceAccessPrivilege() await checkAndApplyDeviceAccessPrivilege()
@@ -313,6 +342,7 @@ export async function createNewWindow(url, access_token, refresh_token,sandbox=f
show: false, show: false,
icon: icon, icon: icon,
webPreferences: { webPreferences: {
partition: 'persist:my-shared-session',
contextIsolation: false, contextIsolation: false,
nodeIntegration: true, nodeIntegration: true,
nodeIntegrationInWorker: true, nodeIntegrationInWorker: true,
@@ -329,9 +359,25 @@ export async function createNewWindow(url, access_token, refresh_token,sandbox=f
registerShortcuts(difyfullScreenWindow) registerShortcuts(difyfullScreenWindow)
}) })
let code = `localStorage.setItem("IsHsAiApp","IsHsAiApp");localStorage.setItem("console_token","${access_token}");localStorage.setItem("refresh_token","12");`
const isAdmin = getStoreValue("isAdmin")
const hs_version = getStoreValue("hs_version") const hs_version = getStoreValue("hs_version")
const dify_csrf_token = getStoreValue("dify_csrf_token")
const cookieStatements = [
`document.cookie = "access_token=${access_token}; path=/";`,
`document.cookie = "refresh_token=${refresh_token}; path=/";`,
`document.cookie = "csrf_token=${dify_csrf_token}; path=/";`,
`document.cookie = "hs_version=${hs_version}; path=/";`
].join('\n');
const localStorageStatements = [
`localStorage.setItem("IsHsAiApp", "IsHsAiApp");`,
`localStorage.setItem("console_token", "${access_token}");`,
`localStorage.setItem("refresh_token", "12");`
].join('\n');
let code = `${localStorageStatements}\n${cookieStatements};`;
const isAdmin = getStoreValue("isAdmin")
let display=''; let display='';
if (isAdmin==true){ if (isAdmin==true){
@@ -354,7 +400,7 @@ export async function createNewWindow(url, access_token, refresh_token,sandbox=f
` `
} }
code=code+`document.cookie="hs_version=${hs_version}";` code=code+`;document.cookie="hs_version=${hs_version}; path=/";`
difyfullScreenWindow.webContents.on('did-finish-load', () => { difyfullScreenWindow.webContents.on('did-finish-load', () => {
difyfullScreenWindow.webContents difyfullScreenWindow.webContents
@@ -364,6 +410,7 @@ export async function createNewWindow(url, access_token, refresh_token,sandbox=f
.catch((error) => { .catch((error) => {
console.error('Error:', error) console.error('Error:', error)
}) })
startCookieLogger(2000)
let times = 0 let times = 0
let timer = setInterval(() => { let timer = setInterval(() => {
if (times > 3) { if (times > 3) {
@@ -387,12 +434,16 @@ export async function createNewWindow(url, access_token, refresh_token,sandbox=f
// 监听快捷键 F12 来打开/关闭 DevTools // 监听快捷键 F12 来打开/关闭 DevTools
difyfullScreenWindow.webContents.on('before-input-event', (event, input) => { difyfullScreenWindow.webContents.on('before-input-event', (event, input) => {
if (input.key === 'F12') { const isDebugger=getStoreValue("isDebugger");
difyfullScreenWindow.webContents.toggleDevTools() if (isDebugger==1){
} else if (input.key === 'F5') { if (input.key === 'F12') {
logger.info('全屏窗口 F5 快捷键触发') difyfullScreenWindow.webContents.toggleDevTools()
difyfullScreenWindow.reload() } else if (input.key === 'F5') {
logger.info('全屏窗口 F5 快捷键触发')
difyfullScreenWindow.reload()
}
} }
}) })
difyfullScreenWindow.webContents.setWindowOpenHandler((details) => { difyfullScreenWindow.webContents.setWindowOpenHandler((details) => {
@@ -403,6 +454,10 @@ export async function createNewWindow(url, access_token, refresh_token,sandbox=f
difyfullScreenWindow.on('closed', () => { difyfullScreenWindow.on('closed', () => {
logger.info('主窗口已关闭') logger.info('主窗口已关闭')
difyfullScreenWindow = null difyfullScreenWindow = null
if (cookieLogTimer) {
clearInterval(cookieLogTimer)
cookieLogTimer = null
}
}) })
difyfullScreenWindow.webContents.on('did-navigate', (event, url) => { difyfullScreenWindow.webContents.on('did-navigate', (event, url) => {
@@ -503,18 +558,18 @@ export async function createNewWindow(url, access_token, refresh_token,sandbox=f
difyfullScreenWindow.webContents.on('did-fail-load', async (event, errorCode, errorDescription, validatedURL) => { difyfullScreenWindow.webContents.on('did-fail-load', async (event, errorCode, errorDescription, validatedURL) => {
logger.error(`全屏窗口页面加载失败: code=${errorCode}, desc=${errorDescription}, url=${validatedURL}, 失败次数: ${failLoadCount + 1}`) logger.error(`全屏窗口页面加载失败: code=${errorCode}, desc=${errorDescription}, url=${validatedURL}, 失败次数: ${failLoadCount + 1}`)
failLoadCount++; failLoadCount++;
if (failLoadCount <= maxRetries) { if (failLoadCount <= maxRetries) {
logger.info(`全屏窗口页面加载失败,${retryDelay}ms后进行第${failLoadCount}次重试...`); logger.info(`全屏窗口页面加载失败,${retryDelay}ms后进行第${failLoadCount}次重试...`);
setTimeout(async () => { setTimeout(async () => {
try { try {
// 在重试前先检查网络连接 // 在重试前先检查网络连接
const { checkDefaultClientConnection } = await import('./utils/networkUtils.js'); const { checkDefaultClientConnection } = await import('./utils/networkUtils.js');
const isNetworkConnected = await checkDefaultClientConnection(3000); const isNetworkConnected = await checkDefaultClientConnection(3000);
if (isNetworkConnected) { if (isNetworkConnected) {
logger.info('网络连接正常,重新加载全屏窗口页面'); logger.info('网络连接正常,重新加载全屏窗口页面');
difyfullScreenWindow.reload(); difyfullScreenWindow.reload();
@@ -544,6 +599,93 @@ export async function createNewWindow(url, access_token, refresh_token,sandbox=f
} }
/**
* 获取并打印全屏窗口的 Cookie 数据
* 每次调用从当前页面会话中读取 Cookie 并输出到控制台
*/
export async function logDifyFullScreenCookies() {
try {
if (!difyfullScreenWindow || difyfullScreenWindow.isDestroyed()) {
return
}
const wc = difyfullScreenWindow.webContents
const currentURL = wc.getURL()
const sess = wc.session
let cookies = []
if (currentURL && typeof currentURL === 'string' && currentURL.length > 0) {
cookies = await sess.cookies.get({ url: currentURL })
} else {
cookies = await sess.cookies.get({})
}
const simplified = cookies.map(c => ({
name: c.name,
value: c.value,
domain: c.domain,
path: c.path,
httpOnly: c.httpOnly,
secure: c.secure,
sameSite: c.sameSite
}))
logger.info('difyfullScreenWindow cookies:', simplified)
const needSync = new Set(['access_token', 'csrf_token', 'refresh_token'])
for (const c of cookies) {
if (needSync.has(c.name)) {
if (c.name === 'access_token') {
setStoreValue('dify_access_token', c.value)
} else if (c.name === 'csrf_token') {
setStoreValue('dify_csrf_token', c.value)
} else if (c.name === 'refresh_token') {
setStoreValue('dify_refresh_token', c.value)
}
await setCookieToMainWindow(c.name, c.value)
}
}
} catch (error) {
logger.error('获取 Cookie 失败:', error)
}
}
/**
* 启动 Cookie 轮询打印
* 以指定间隔定时获取并打印 Cookie默认 2000ms
* 如果已在运行则不会重复启动
*/
export function startCookieLogger(intervalMs = 2000) {
if (cookieLogTimer) {
return
}
cookieLogTimer = setInterval(() => {
logDifyFullScreenCookies()
}, intervalMs)
}
/**
* 将指定名称和值的 Cookie 写入主窗口
*/
async function setCookieToMainWindow(name, value) {
try {
if (!mainWindow || mainWindow.isDestroyed()) {
return
}
const targetBase = getStoreValue('h5_client_url') || ''
const targetUrl = targetBase ? `${targetBase}/` : (mainWindow.webContents.getURL() || 'http://localhost/')
const msess = mainWindow.webContents.session
await msess.cookies.set({
url: targetUrl,
name,
value,
path: '/'
})
await mainWindow.webContents.executeJavaScript(`document.cookie = "${name}=${value}; path=/";`)
logger.info(`已写入主窗口 Cookie: ${name}`)
} catch (error) {
logger.error('写入主窗口 Cookie 失败:', error)
}
}
export function createDrageWindow() { export function createDrageWindow() {
logger.info('开始创建悬浮窗口') logger.info('开始创建悬浮窗口')
@@ -564,6 +706,7 @@ export function createDrageWindow() {
alwaysOnTop: true, alwaysOnTop: true,
autoHideMenuBar: true, autoHideMenuBar: true,
webPreferences: { webPreferences: {
partition: 'persist:my-shared-session',
contextIsolation: false, contextIsolation: false,
nodeIntegration: true, nodeIntegration: true,
nodeIntegrationInWorker: true, nodeIntegrationInWorker: true,
@@ -606,18 +749,18 @@ export function createDrageWindow() {
drageWindow.webContents.on('did-fail-load', async (event, errorCode, errorDescription, validatedURL) => { drageWindow.webContents.on('did-fail-load', async (event, errorCode, errorDescription, validatedURL) => {
logger.error(`悬浮窗口页面加载失败: code=${errorCode}, desc=${errorDescription}, url=${validatedURL}, 失败次数: ${drageFailLoadCount + 1}`) logger.error(`悬浮窗口页面加载失败: code=${errorCode}, desc=${errorDescription}, url=${validatedURL}, 失败次数: ${drageFailLoadCount + 1}`)
drageFailLoadCount++; drageFailLoadCount++;
if (drageFailLoadCount <= drageMaxRetries) { if (drageFailLoadCount <= drageMaxRetries) {
logger.info(`悬浮窗口页面加载失败,${drageRetryDelay}ms后进行第${drageFailLoadCount}次重试...`); logger.info(`悬浮窗口页面加载失败,${drageRetryDelay}ms后进行第${drageFailLoadCount}次重试...`);
setTimeout(async () => { setTimeout(async () => {
try { try {
// 在重试前先检查网络连接 // 在重试前先检查网络连接
const { checkDefaultClientConnection } = await import('./utils/networkUtils.js'); const { checkDefaultClientConnection } = await import('./utils/networkUtils.js');
const isNetworkConnected = await checkDefaultClientConnection(3000); const isNetworkConnected = await checkDefaultClientConnection(3000);
if (isNetworkConnected) { if (isNetworkConnected) {
logger.info('网络连接正常,重新加载悬浮窗口页面'); logger.info('网络连接正常,重新加载悬浮窗口页面');
drageWindow.reload(); drageWindow.reload();
@@ -761,6 +904,7 @@ export function createConfigWindow() {
parent: getMainWindow(), parent: getMainWindow(),
modal: true, modal: true,
webPreferences: { webPreferences: {
partition: 'persist:my-shared-session',
contextIsolation: false, contextIsolation: false,
nodeIntegration: true, nodeIntegration: true,
nodeIntegrationInWorker: true, nodeIntegrationInWorker: true,