From abe131fedc957041778a6cf57f50fa833076c890 Mon Sep 17 00:00:00 2001 From: "LUOJIE\\coolp" Date: Tue, 23 Dec 2025 20:57:07 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=9E=E7=8E=B0=E5=AE=A2=E6=88=B7=E7=AB=AF?= =?UTF-8?q?=E7=9A=84=E5=8D=95=E7=82=B9=E7=99=BB=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env.shenranqi | 2 +- .idea/misc.xml | 2 +- electron-builder.yml | 6 +- package.json | 27 +++++-- src/main/index.js | 115 +++++++++++++++++++++++++++--- src/main/tray.js | 2 +- src/main/utils/WebSocketClient.js | 6 +- src/main/window.js | 50 +++++++++++++ src/preload/index.js | 36 +++++++--- 9 files changed, 214 insertions(+), 32 deletions(-) diff --git a/.env.shenranqi b/.env.shenranqi index 0038c9a..91cfb8b 100644 --- a/.env.shenranqi +++ b/.env.shenranqi @@ -1,4 +1,4 @@ -VITE_h5_client_url=http://10.9.18.138:18900 +VITE_h5_client_url=https://aiagent.szgas.com.cn ### VITE_h5_client_url=https://bqw-120.ii999.live:20038 #VITE_h5_client_url=http://127.0.0.1:18901 VITE_HsAppCode=1 diff --git a/.idea/misc.xml b/.idea/misc.xml index 07115cd..995c32c 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,6 +1,6 @@ - + \ No newline at end of file diff --git a/electron-builder.yml b/electron-builder.yml index 4a9a671..7468f0b 100644 --- a/electron-builder.yml +++ b/electron-builder.yml @@ -1,4 +1,4 @@ -appId: com.huashiai.dify-market-manager-gui +appId: com.szgas.dify-market-manager-gui compression: maximum productName: 深燃智能体平台 directories: @@ -12,7 +12,7 @@ files: asarUnpack: - resources/** win: - executableName: 深燃智能体平台 + executableName: 深圳燃气智能体平台 nsis: artifactName: ${name}-${version}-setup.${ext} shortcutName: ${productName} @@ -32,7 +32,7 @@ linux: target: - AppImage - deb - maintainer: huashiai.org + maintainer: szgas.org category: Utility appImage: artifactName: ${name}-${version}.${ext} diff --git a/package.json b/package.json index b889264..558506e 100644 --- a/package.json +++ b/package.json @@ -1,10 +1,10 @@ { - "name": "dify-market-manager-gui", + "name": "SZGAS_AIAgent", "version": "1.0.0", - "description": "百千万AI智能体共创平台", + "description": "深圳燃气 AI智能体", "main": "./out/main/index.js", - "author": "huashiai.com", - "homepage": "https://huashiai.com", + "author": "szgas.com", + "homepage": "https://szgas.com", "scripts": { "format": "prettier --write .", "lint": "eslint --cache .", @@ -37,6 +37,24 @@ "build:icon": "./node_modules/.bin/electron-icon-builder --input=./build/icon.png --output=./build/", "make": "electron-forge make" }, + "build": { + "protocols": [{ + "name": "aiAgent Protocol", + "schemes": ["aiAgent"] + }], + "win": { + "target": "nsis", + "signingHashAlgorithms": ["sha256"] + }, + "mac": { + "extendInfo": { + "CFBundleURLTypes": [{ + "CFBundleURLName": "MyApp Protocol", + "CFBundleURLSchemes": ["myapp"] + }] + } + } + }, "permissions": [ "audioCapture", "videoCapture" @@ -51,6 +69,7 @@ "electron-log": "^5.4.0", "electron-store": "^8.0.0", "electron-updater": "^6.3.9", + "jquery": "^3.7.1", "ws": "^8.18.2", "xe-utils": "^3.7.4" }, diff --git a/src/main/index.js b/src/main/index.js index afae3ff..607ee24 100644 --- a/src/main/index.js +++ b/src/main/index.js @@ -1,7 +1,7 @@ import { app, shell, BrowserWindow, ipcMain, Menu, session, screen, dialog } from 'electron' import { electronApp, optimizer } from '@electron-toolkit/utils' import Store from 'electron-store' -import { createWindow, createDrageWindow, unregisterAllShortcuts, getMainWindow } from './window.js' +import { createWindow, createDrageWindow, unregisterAllShortcuts, getMainWindow,createOAuthWindow } from './window.js' import { setupIPC } from './ipc.js' import { createTray, destroyTray,clearBrowserCache } from './tray.js' import XEUtils from 'xe-utils' @@ -15,6 +15,8 @@ import { setStoreValue, getStoreValue ,deleteStore} from './store.js' import AutoLaunch from 'auto-launch' import axios from 'axios' +const PROTOCOL_NAME = 'aiAgent' + import WebSocketClient from './utils/WebSocketClient'; let wsClient=null @@ -150,7 +152,7 @@ function cleanupCacheDirectories() { } } } - + deleteRecursive(cachePath) logger.info(`缓存目录清理完成: ${cachePath}`) } catch (error) { @@ -163,6 +165,81 @@ function cleanupCacheDirectories() { } } +/** + * 注册自定义协议为系统默认处理程序 + */ +function registerDeepLinkProtocol() { + try { + if (process.platform === 'win32') { + if (process.defaultApp) { + app.setAsDefaultProtocolClient(PROTOCOL_NAME, process.execPath, [path.resolve(process.argv[1])]) + } else { + app.setAsDefaultProtocolClient(PROTOCOL_NAME) + } + } else { + app.setAsDefaultProtocolClient(PROTOCOL_NAME) + } + logger.info(`已注册自定义协议: ${PROTOCOL_NAME}`) + } catch (error) { + logger.error('注册自定义协议失败:', error) + } +} + +/** + * 从命令行参数提取深链地址与 code 参数 + * 返回对象 { url, code };未找到返回 null + */ +function extractDeepLinkFromArgs(args = []) { + try { + const protoPrefix = `${PROTOCOL_NAME.toLowerCase()}://` + const found = (args || []).find( + (arg) => typeof arg === 'string' && arg.toLowerCase().startsWith(protoPrefix) + ) + if (!found) return null + + let code = null + try { + const u = new URL(found) + const params = new URLSearchParams(u.search || '') + code = params.get('code') + } catch (e) { + const m = found.match(/[?&]code=([^&]+)/i) + code = m ? decodeURIComponent(m[1]) : null + } + + return { url: found, code } + } catch (error) { + logger.error('提取深链地址失败:', error) + return null + } +} + +/** + * 处理深链地址 + */ +function handleDeepLink(payload) { + try { + const url = typeof payload === 'string' ? payload : payload?.url + const code = typeof payload === 'object' ? payload?.code : null + logger.info('Deep link URL:', url) + if (code) { + logger.info('Deep link code:', code) + } + const mainWindow = BrowserWindow.getAllWindows()[0] || getMainWindow() + if (mainWindow) { + const h5_client_url=getStoreValue("h5_client_url")+"/pc_client/autologin?code="+code + + logger.info("==================================== mainWindow.loadURL:"+h5_client_url) + // 加载存储的 URL + mainWindow.loadURL(h5_client_url) + mainWindow.show() + mainWindow.focus() + } + } catch (error) { + logger.error('处理深链地址失败:', error) + } +} + /** * 单应用启动实现 * 请求单一实例锁, @@ -181,6 +258,10 @@ if (!gotTheLock) { // 监听第二个实例被运行时 app.on('second-instance', (event, commandLine, workingDirectory) => { logger.info('检测到第二个实例启动,激活现有实例') + const deeplink = extractDeepLinkFromArgs(commandLine) + if (deeplink) { + handleDeepLink(deeplink) + } // 当有第二个实例被运行时,激活之前的实例并将焦点置于其窗口 const windows = BrowserWindow.getAllWindows() if (windows.length > 0) { @@ -196,6 +277,8 @@ if (!gotTheLock) { app.whenReady().then(() => { logger.info('应用已准备就绪,开始初始化...'); + registerDeepLinkProtocol() + // 清理缓存目录 cleanupCacheDirectories() @@ -213,6 +296,8 @@ if (!gotTheLock) { optimizer.watchWindowShortcuts(window) }) + + // 根据存储的状态决定是否创建悬浮窗口 if (getStoreValue('showDrageWindow')) { createDrageWindow() @@ -247,8 +332,20 @@ if (!gotTheLock) { }) logger.info('应用初始化完成'); + + const initialDeeplink = extractDeepLinkFromArgs(process.argv) + if (initialDeeplink) { + handleDeepLink(initialDeeplink) + } }) + app.on('open-url', (event, url) => { + logger.info('Opened with URL:', url) + event.preventDefault() + // 处理url,例如解析参数并打开相应窗口 + logger.info('Opened with URL:', url) + }) + // 修改窗口关闭行为 app.on('window-all-closed', async (event) => { if (process.platform !== 'darwin') { @@ -258,7 +355,7 @@ if (!gotTheLock) { logger.info('检测到重启过程,跳过窗口关闭处理') return; } - + if (!app.isQuiting) { logger.info('用户关闭窗口,隐藏应用') // 如果不是主动退出,则隐藏所有窗口 @@ -272,7 +369,7 @@ if (!gotTheLock) { } catch (error) { logger.error('窗口关闭时清理缓存失败:', error); } - + // 销毁托盘并退出应用 destroyTray() app.quit(); @@ -293,7 +390,7 @@ if (!gotTheLock) { logger.info('检测到重启过程,跳过before-quit处理') return; } - + logger.info('应用即将退出,开始清理资源') // 在应用程序即将退出时执行操作,例如保存数据 event.preventDefault(); @@ -304,7 +401,7 @@ if (!gotTheLock) { } catch (error) { logger.error('应用退出时清理缓存失败:', error); } - + // 销毁托盘并退出应用 destroyTray() // 使用 exit 确保完全退出 @@ -331,7 +428,7 @@ if (!gotTheLock) { unregisterAllShortcuts() destroyTray() - + // 清理完成后退出应用,使用 exit 确保完全退出 app.exit(0); }) @@ -394,7 +491,7 @@ export function checkIsKeepAlive(){ setStoreValue("lastAliveTime",dayjs()) } } - + }, 1000 * 2) -} \ No newline at end of file +} diff --git a/src/main/tray.js b/src/main/tray.js index 613c3ba..01ff82b 100644 --- a/src/main/tray.js +++ b/src/main/tray.js @@ -90,7 +90,7 @@ export function createTray() { tray = new Tray(icon) // 设置托盘图标的提示文本 - tray.setToolTip('Dify Market Manager') + tray.setToolTip('深圳燃气 AI智能体') // 创建右键菜单 const contextMenu = Menu.buildFromTemplate([ diff --git a/src/main/utils/WebSocketClient.js b/src/main/utils/WebSocketClient.js index 2a92690..3462786 100644 --- a/src/main/utils/WebSocketClient.js +++ b/src/main/utils/WebSocketClient.js @@ -81,7 +81,7 @@ class WebSocketClient { setTimeout(() => { this.lockReconnect = false; - this.createConnect(); // 重新获取本地缓存并创建连接 + // this.createConnect(); // 重新获取本地缓存并创建连接 }, this.reconnectInterval); } @@ -108,7 +108,7 @@ class WebSocketClient { try { const messageStr = data.toString(); const message = JSON.parse(messageStr); - + // 减少心跳消息的日志打印 if (message.cmd === 'heartcheck') { // 心跳消息不打印日志,或者只在调试模式下打印 @@ -118,7 +118,7 @@ class WebSocketClient { } else { logger.info('收到消息:', messageStr); } - + this.handleMessage(message); } catch (error) { logger.error('消息解析错误:', error); diff --git a/src/main/window.js b/src/main/window.js index 2a12371..7c96a15 100644 --- a/src/main/window.js +++ b/src/main/window.js @@ -13,6 +13,7 @@ import {checkForUpdates} from "./utils/updateUtils" import dayjs from 'dayjs' let mainWindow = null +let oauthWindow = null let difyfullScreenWindow = null let drageWindow = null let apiConfigWindow = null @@ -51,6 +52,49 @@ async function checkAndApplyDeviceAccessPrivilege() { } } +export async function createOAuthWindow(){ + logger.info('创建授权窗口') + + Menu.setApplicationMenu(null) + + // Create the browser window. + oauthWindow = new BrowserWindow({ + width: 1480, + height: 980, + minWidth: 1480, + minHeight: 980, + show: false, + media: { + audio: true, + video: true + }, + icon: icon, + webPreferences: { + nodeIntegration: false, + nodeIntegrationInWorker: true, + preload: join(__dirname, '../preload/index.js'), + // sandbox: false + } + }) + + // 检查本地存储中是否已有 h5_client_url + const existingH5ClientUrl = getStoreValue("h5_client_url") + if (!existingH5ClientUrl || existingH5ClientUrl.trim() === '') { + // 只有当值不存在或为空时,才设置默认值 + // setStoreValue("h5_client_url", "http://work.ii999.live:20040") + // setStoreValue("h5_client_url", "http://10.102.8.56:18900") + // setStoreValue("h5_client_url", "http://68.66.24.160:18900") + setStoreValue("h5_client_url", import.meta.env.VITE_h5_client_url) + } + + const h5_client_url=getStoreValue("h5_client_url")+"/pc_client/autologin" + + logger.info("==================================== mainWindow.loadURL:"+h5_client_url) + // 加载存储的 URL + oauthWindow.loadURL(h5_client_url) + + +} export async function createWindow() { // 如果窗口已经存在,直接显示并返回 @@ -63,6 +107,9 @@ export async function createWindow() { Menu.setApplicationMenu(null) + // createOAuthWindow() + // return + // Create the browser window. mainWindow = new BrowserWindow({ width: 1480, @@ -300,6 +347,9 @@ function registerShortcuts(window=null) { app.on('will-quit', () => { globalShortcut.unregisterAll() // 注销所有快捷键 }) + + + } export async function createNewWindow(url, access_token, refresh_token,sandbox=false) { diff --git a/src/preload/index.js b/src/preload/index.js index 2b2448a..9be58a5 100644 --- a/src/preload/index.js +++ b/src/preload/index.js @@ -1,21 +1,16 @@ -import { contextBridge , ipcRenderer} from 'electron' +import { contextBridge, ipcRenderer } from 'electron' import { electronAPI } from '@electron-toolkit/preload' // Custom APIs for renderer const api = {} -// Use `contextBridge` APIs to expose Electron APIs to -// renderer only if context isolation is enabled, otherwise -// just add to the DOM global. if (process.contextIsolated) { try { contextBridge.exposeInMainWorld('electron', electronAPI) contextBridge.exposeInMainWorld('api', api) - - ipcRenderer.on('data-from-main', (event, key,value) => { - localStorage.setItem(key, value); - }); - + ipcRenderer.on('data-from-main', (event, key, value) => { + localStorage.setItem(key, value) + }) } catch (error) { console.error(error) } @@ -23,5 +18,26 @@ if (process.contextIsolated) { window.electron = electronAPI window.api = api - + // ✅ 重点修复:覆盖 require('jquery') 让它返回 jQuery + try { + // 保存原始 require 避免循环 + const originalRequire = require; + // 重写 require 函数,让 'jquery' 请求返回 jQuery + require = (request) => { + if (request === 'jquery') { + // 确保 jQuery 已加载 + if (!window.jQuery) { + window.jQuery = originalRequire('jquery'); + window.$ = window.jQuery; + } + return window.jQuery; + } + return originalRequire(request); + }; + // 初始化 jQuery(触发上面的逻辑) + window.jQuery = require('jquery'); + window.$ = window.jQuery; + } catch (e) { + console.error('Failed to load jQuery:', e); + } }