diff --git a/package-lock.json b/package-lock.json index 72f8f79..7892832 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,8 +11,6 @@ "dependencies": { "long": "^5.3.2", "protobufjs": "^8.0.0", - "socket.io": "^4.8.3", - "socket.io-client": "^4.8.3", "ws": "^8.19.0" }, "devDependencies": { @@ -1066,21 +1064,6 @@ "win32" ] }, - "node_modules/@socket.io/component-emitter": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz", - "integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==", - "license": "MIT" - }, - "node_modules/@types/cors": { - "version": "2.8.19", - "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.19.tgz", - "integrity": "sha512-mFNylyeyqN93lfe/9CSxOGREz8cpzAhH+E93xJ4xWQf62V8sQ/24reV2nyzUWM6H6Xji+GGHpkbLe7pVoUEskg==", - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, "node_modules/@types/estree": { "version": "1.0.8", "resolved": "https://registry.npmmirror.com/@types/estree/-/estree-1.0.8.tgz", @@ -1449,28 +1432,6 @@ } } }, - "node_modules/accepts": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", - "license": "MIT", - "dependencies": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/accepts/node_modules/negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, "node_modules/acorn": { "version": "8.15.0", "resolved": "https://registry.npmmirror.com/acorn/-/acorn-8.15.0.tgz", @@ -1532,15 +1493,6 @@ "dev": true, "license": "MIT" }, - "node_modules/base64id": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", - "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==", - "license": "MIT", - "engines": { - "node": "^4.5.0 || >= 5.9" - } - }, "node_modules/birpc": { "version": "2.9.0", "resolved": "https://registry.npmmirror.com/birpc/-/birpc-2.9.0.tgz", @@ -1574,15 +1526,6 @@ "dev": true, "license": "MIT" }, - "node_modules/cookie": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", - "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, "node_modules/copy-anything": { "version": "4.0.5", "resolved": "https://registry.npmmirror.com/copy-anything/-/copy-anything-4.0.5.tgz", @@ -1599,23 +1542,6 @@ "url": "https://github.com/sponsors/mesqueeb" } }, - "node_modules/cors": { - "version": "2.8.6", - "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.6.tgz", - "integrity": "sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw==", - "license": "MIT", - "dependencies": { - "object-assign": "^4", - "vary": "^1" - }, - "engines": { - "node": ">= 0.10" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, "node_modules/csstype": { "version": "3.2.3", "resolved": "https://registry.npmmirror.com/csstype/-/csstype-3.2.3.tgz", @@ -1630,23 +1556,6 @@ "dev": true, "license": "MIT" }, - "node_modules/debug": { - "version": "4.4.3", - "resolved": "https://registry.npmmirror.com/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, "node_modules/element-plus": { "version": "2.13.2", "resolved": "https://registry.npmmirror.com/element-plus/-/element-plus-2.13.2.tgz", @@ -1673,90 +1582,6 @@ "vue": "^3.3.0" } }, - "node_modules/engine.io": { - "version": "6.6.5", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.6.5.tgz", - "integrity": "sha512-2RZdgEbXmp5+dVbRm0P7HQUImZpICccJy7rN7Tv+SFa55pH+lxnuw6/K1ZxxBfHoYpSkHLAO92oa8O4SwFXA2A==", - "license": "MIT", - "dependencies": { - "@types/cors": "^2.8.12", - "@types/node": ">=10.0.0", - "accepts": "~1.3.4", - "base64id": "2.0.0", - "cookie": "~0.7.2", - "cors": "~2.8.5", - "debug": "~4.4.1", - "engine.io-parser": "~5.2.1", - "ws": "~8.18.3" - }, - "engines": { - "node": ">=10.2.0" - } - }, - "node_modules/engine.io-client": { - "version": "6.6.4", - "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.6.4.tgz", - "integrity": "sha512-+kjUJnZGwzewFDw951CDWcwj35vMNf2fcj7xQWOctq1F2i1jkDdVvdFG9kM/BEChymCH36KgjnW0NsL58JYRxw==", - "license": "MIT", - "dependencies": { - "@socket.io/component-emitter": "~3.1.0", - "debug": "~4.4.1", - "engine.io-parser": "~5.2.1", - "ws": "~8.18.3", - "xmlhttprequest-ssl": "~2.1.1" - } - }, - "node_modules/engine.io-client/node_modules/ws": { - "version": "8.18.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", - "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", - "license": "MIT", - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/engine.io-parser": { - "version": "5.2.3", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.3.tgz", - "integrity": "sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==", - "license": "MIT", - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/engine.io/node_modules/ws": { - "version": "8.18.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", - "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", - "license": "MIT", - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, "node_modules/entities": { "version": "7.0.1", "resolved": "https://registry.npmmirror.com/entities/-/entities-7.0.1.tgz", @@ -1988,27 +1813,6 @@ "dev": true, "license": "MIT" }, - "node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmmirror.com/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmmirror.com/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "license": "MIT", - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, "node_modules/mitt": { "version": "3.0.1", "resolved": "https://registry.npmmirror.com/mitt/-/mitt-3.0.1.tgz", @@ -2048,12 +1852,6 @@ "pathe": "^2.0.1" } }, - "node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmmirror.com/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "license": "MIT" - }, "node_modules/muggle-string": { "version": "0.4.1", "resolved": "https://registry.npmmirror.com/muggle-string/-/muggle-string-0.4.1.tgz", @@ -2087,15 +1885,6 @@ "dev": true, "license": "BSD-3-Clause" }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/path-browserify": { "version": "1.0.1", "resolved": "https://registry.npmmirror.com/path-browserify/-/path-browserify-1.0.1.tgz", @@ -2292,83 +2081,6 @@ "dev": true, "license": "MIT" }, - "node_modules/socket.io": { - "version": "4.8.3", - "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.8.3.tgz", - "integrity": "sha512-2Dd78bqzzjE6KPkD5fHZmDAKRNe3J15q+YHDrIsy9WEkqttc7GY+kT9OBLSMaPbQaEd0x1BjcmtMtXkfpc+T5A==", - "license": "MIT", - "dependencies": { - "accepts": "~1.3.4", - "base64id": "~2.0.0", - "cors": "~2.8.5", - "debug": "~4.4.1", - "engine.io": "~6.6.0", - "socket.io-adapter": "~2.5.2", - "socket.io-parser": "~4.2.4" - }, - "engines": { - "node": ">=10.2.0" - } - }, - "node_modules/socket.io-adapter": { - "version": "2.5.6", - "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.6.tgz", - "integrity": "sha512-DkkO/dz7MGln0dHn5bmN3pPy+JmywNICWrJqVWiVOyvXjWQFIv9c2h24JrQLLFJ2aQVQf/Cvl1vblnd4r2apLQ==", - "license": "MIT", - "dependencies": { - "debug": "~4.4.1", - "ws": "~8.18.3" - } - }, - "node_modules/socket.io-adapter/node_modules/ws": { - "version": "8.18.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", - "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", - "license": "MIT", - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/socket.io-client": { - "version": "4.8.3", - "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.8.3.tgz", - "integrity": "sha512-uP0bpjWrjQmUt5DTHq9RuoCBdFJF10cdX9X+a368j/Ft0wmaVgxlrjvK3kjvgCODOMMOz9lcaRzxmso0bTWZ/g==", - "license": "MIT", - "dependencies": { - "@socket.io/component-emitter": "~3.1.0", - "debug": "~4.4.1", - "engine.io-client": "~6.6.1", - "socket.io-parser": "~4.2.4" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/socket.io-parser": { - "version": "4.2.5", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.5.tgz", - "integrity": "sha512-bPMmpy/5WWKHea5Y/jYAP6k74A+hvmRCQaJuJB6I/ML5JZq/KfNieUVo/3Mh7SAqn7TyFdIo6wqYHInG1MU1bQ==", - "license": "MIT", - "dependencies": { - "@socket.io/component-emitter": "~3.1.0", - "debug": "~4.4.1" - }, - "engines": { - "node": ">=10.0.0" - } - }, "node_modules/source-map-js": { "version": "1.2.1", "resolved": "https://registry.npmmirror.com/source-map-js/-/source-map-js-1.2.1.tgz", @@ -2478,15 +2190,6 @@ "url": "https://github.com/sponsors/sxzz" } }, - "node_modules/vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, "node_modules/vite": { "version": "7.3.1", "resolved": "https://registry.npmmirror.com/vite/-/vite-7.3.1.tgz", @@ -2682,14 +2385,6 @@ } } }, - "node_modules/xmlhttprequest-ssl": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.1.2.tgz", - "integrity": "sha512-TEU+nJVUUnA4CYJFLvK5X9AOeH4KvDvhIfm0vV1GaQRtchnG0hgK5p8hw/xjv8cunWYCsiPCSDzObPyhEwq3KQ==", - "engines": { - "node": ">=0.4.0" - } - }, "node_modules/yaml": { "version": "2.8.2", "resolved": "https://registry.npmmirror.com/yaml/-/yaml-2.8.2.tgz", diff --git a/package.json b/package.json index db23e18..67d71a7 100644 --- a/package.json +++ b/package.json @@ -14,8 +14,6 @@ "dependencies": { "long": "^5.3.2", "protobufjs": "^8.0.0", - "socket.io": "^4.8.3", - "socket.io-client": "^4.8.3", "ws": "^8.19.0" }, "devDependencies": { diff --git a/server/ipc.js b/server/ipc.js index f03d653..d45404b 100644 --- a/server/ipc.js +++ b/server/ipc.js @@ -1,100 +1,70 @@ /** - * IPC 通道处理 - * 注册所有 ipcMain.handle 通道,调用 bot.js 并返回结果 - * 将 bot.js 事件推送到渲染进程 + * WebSocket 通道 - 替代 Socket.IO,更简单的路径配置 */ -const {Server} = require('socket.io'); +const { WebSocketServer } = require('ws'); const bot = require('./bot'); -let io = null; - -function handle(socket, ev, cb) { - if (!io) - throw new Error('IPC 尚未初始化'); - socket.on(ev, async (data, ioCb) => { - try { - ioCb(await cb(data)); - } catch (e) { - ioCb({success: false, error: e.message,}); - } +let wss = null; +const WS_PATH = '/ws'; + +// 命令映射 +const HANDLERS = { + 'bot:connect': async (d) => await bot.botConnect(d.code, d.platform), + 'bot:disconnect': () => bot.botDisconnect(), + 'bot:status': () => bot.getStatus(), + 'bot:feature-toggle': (d) => bot.setFeatureEnabled(d.feature, d.enabled), + 'bot:get-config': () => bot.getConfig(), + 'bot:save-config': (d) => bot.saveConfig(d), + 'bot:get-plant-plan': () => bot.getPlantPlan(), + 'bot:get-logs': () => bot.getLogs(), + 'bot:clear-logs': () => { bot.clearLogs(); return { success: true }; }, +}; + +function broadcast(msg) { + if (!wss) return; + const data = JSON.stringify(msg); + wss.clients.forEach((client) => { + if (client.readyState === 1) client.send(data); }); } -/** - * 注册所有 IPC 通道 - */ function registerIPC(server) { - io = new Server(server); - - io.on('connection', (socket) => { - console.log('👤 用户连接:', socket.id); - // socket.onAny((event, ...args) => { - // console.log(`[收到消息] 来自: ${socket.id} | 事件: ${event} | 数据:`, args); - // }); - - // === 请求/响应通道 === - - handle(socket, 'bot:connect', async ({code, platform}) => { - return await bot.botConnect(code, platform); - }); - - handle(socket, 'bot:connect', async ({code, platform}) => { - return await bot.botConnect(code, platform); - }); - - handle(socket, 'bot:disconnect', () => { - return bot.botDisconnect(); - }); - - handle(socket, 'bot:status', () => { - return bot.getStatus(); - }); - - handle(socket, 'bot:feature-toggle', ({feature, enabled}) => { - return bot.setFeatureEnabled(feature, enabled); - }); - - handle(socket, 'bot:get-config', () => { - return bot.getConfig(); - }); - - handle(socket, 'bot:save-config', (partial) => { - return bot.saveConfig(partial); - }); - - handle(socket, 'bot:get-plant-plan', () => { - return bot.getPlantPlan(); - }); - - handle(socket, 'bot:get-logs', () => { - return bot.getLogs(); - }); - - handle(socket, 'bot:clear-logs', () => { - bot.clearLogs(); - return {success: true}; + wss = new WebSocketServer({ server, path: WS_PATH }); + + wss.on('connection', (ws, req) => { + console.log('👤 WebSocket 连接:', req.socket.remoteAddress); + + ws.on('message', async (raw) => { + try { + const msg = JSON.parse(raw.toString()); + if (msg.t !== 'req' || !msg.id || !msg.ch) return; + + const fn = HANDLERS[msg.ch]; + if (!fn) { + ws.send(JSON.stringify({ t: 'res', id: msg.id, ok: false, err: 'unknown channel' })); + return; + } + + const result = await fn(msg.d || {}); + ws.send(JSON.stringify({ t: 'res', id: msg.id, ok: true, d: result })); + } catch (e) { + const id = (() => { try { const m = JSON.parse(raw.toString()); return m?.id; } catch { return null; } })(); + if (id != null) { + ws.send(JSON.stringify({ t: 'res', id, ok: false, err: e.message })); + } + } }); }); - // === 主进程 → 渲染进程推送 === - - bot.botEvents.on('log', (entry) => { - if (!io) - throw new Error('IPC 尚未初始化'); - io.emit('bot:log', entry); - }); - - bot.botEvents.on('status-update', (status) => { - if (!io) - throw new Error('IPC 尚未初始化'); - io.emit('bot:status-update', status); - }); + bot.botEvents.on('log', (entry) => broadcast({ t: 'ev', ch: 'bot:log', d: entry })); + bot.botEvents.on('status-update', (status) => broadcast({ t: 'ev', ch: 'bot:status-update', d: status })); } async function deployIPC() { - if (!io) return; - await new Promise(resolve => io.close(resolve)); - io = null; + if (!wss) return; + const s = wss; + wss = null; + await new Promise((resolve) => s.close(resolve)); } -module.exports = {registerIPC, deployIPC}; +module.exports = { registerIPC, deployIPC }; diff --git a/server/main.js b/server/main.js index be62c84..4c6d67d 100644 --- a/server/main.js +++ b/server/main.js @@ -4,8 +4,9 @@ const path = require('path'); const bot = require('./bot'); const {registerIPC, deployIPC} = require('./ipc'); -// 静态服务器 +// 静态服务器(/ws 由 WebSocket 处理) const server = http.createServer((req, res) => { + if (req.url === '/ws' || req.url?.startsWith('/ws?')) return; let filePath = path.join(__dirname, '../dist', req.url === '/' ? 'index.html' : req.url); fs.readFile(filePath, (err, content) => { if (err) { @@ -29,8 +30,8 @@ async function main() { registerIPC(server); await bot.init(); - server.listen(3000, () => { - console.log('🚀 服务运行在 http://localhost:3000'); + server.listen(18084, () => { + console.log('🚀 服务运行在 http://localhost:18084'); }); } diff --git a/vite.config.js b/vite.config.js index 30f27d5..b958371 100644 --- a/vite.config.js +++ b/vite.config.js @@ -5,7 +5,7 @@ import path from 'path' export default defineConfig({ plugins: [vue()], root: 'web', - base: './', + base: '/qqfarmbot/', resolve: { alias: { '@': path.resolve(__dirname, 'web/src'), @@ -19,10 +19,11 @@ export default defineConfig({ host: '127.0.0.1', port: 5173, proxy: { - '/socket.io': { - target: 'http://localhost:3000', + '/qqfarmbot/ws': { + target: 'http://localhost:18084', ws: true, changeOrigin: true, + rewrite: () => '/ws', }, }, }, diff --git a/web/index.html b/web/index.html index 1ee9f0d..0c3f0f4 100644 --- a/web/index.html +++ b/web/index.html @@ -2,8 +2,14 @@
- +