Fix:ai服务端口被占用后不启动,避免报错

This commit is contained in:
wanglin2 2025-04-09 22:25:42 +08:00
parent 30404721fa
commit e0ca3a5d12
3 changed files with 80 additions and 51 deletions

View File

@ -1,11 +1,11 @@
{ {
"name": "simple-mind-map", "name": "simple-mind-map",
"version": "0.12.1", "version": "0.14.0",
"lockfileVersion": 2, "lockfileVersion": 2,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"version": "0.12.1", "version": "0.14.0",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@svgdotjs/svg.js": "3.2.0", "@svgdotjs/svg.js": "3.2.0",

11
web/package-lock.json generated
View File

@ -15699,8 +15699,7 @@
"node_modules/viewerjs": { "node_modules/viewerjs": {
"version": "1.11.6", "version": "1.11.6",
"resolved": "https://registry.npmjs.org/viewerjs/-/viewerjs-1.11.6.tgz", "resolved": "https://registry.npmjs.org/viewerjs/-/viewerjs-1.11.6.tgz",
"integrity": "sha512-TlhdSp2oEOLFXvEp4psKaeTjR5zBjTRcM/sHUN8PkV1UWuY8HKC8n7GaVdW5Xqnwdr/F1OmzLik1QwDjI4w/nw==", "integrity": "sha512-TlhdSp2oEOLFXvEp4psKaeTjR5zBjTRcM/sHUN8PkV1UWuY8HKC8n7GaVdW5Xqnwdr/F1OmzLik1QwDjI4w/nw=="
"peer": true
}, },
"node_modules/vm-browserify": { "node_modules/vm-browserify": {
"version": "1.1.2", "version": "1.1.2",
@ -19258,6 +19257,7 @@
"integrity": "sha512-VCNRiAt2P/bLo09rYt3DLe6xXUMlhJwrvU18Ddd/lYJgC7s8+wvhgYs+MTx4OiAXdu58drGwSBO9SPx7C6J82Q==", "integrity": "sha512-VCNRiAt2P/bLo09rYt3DLe6xXUMlhJwrvU18Ddd/lYJgC7s8+wvhgYs+MTx4OiAXdu58drGwSBO9SPx7C6J82Q==",
"dev": true, "dev": true,
"requires": { "requires": {
"@babel/core": "^7.11.0",
"@babel/helper-compilation-targets": "^7.9.6", "@babel/helper-compilation-targets": "^7.9.6",
"@babel/helper-module-imports": "^7.8.3", "@babel/helper-module-imports": "^7.8.3",
"@babel/plugin-proposal-class-properties": "^7.8.3", "@babel/plugin-proposal-class-properties": "^7.8.3",
@ -19270,6 +19270,7 @@
"@vue/babel-plugin-jsx": "^1.0.3", "@vue/babel-plugin-jsx": "^1.0.3",
"@vue/babel-preset-jsx": "^1.2.4", "@vue/babel-preset-jsx": "^1.2.4",
"babel-plugin-dynamic-import-node": "^2.3.3", "babel-plugin-dynamic-import-node": "^2.3.3",
"core-js": "^3.6.5",
"core-js-compat": "^3.6.5", "core-js-compat": "^3.6.5",
"semver": "^6.1.0" "semver": "^6.1.0"
} }
@ -29565,7 +29566,8 @@
"resolved": "https://registry.npmjs.org/v-viewer/-/v-viewer-1.7.4.tgz", "resolved": "https://registry.npmjs.org/v-viewer/-/v-viewer-1.7.4.tgz",
"integrity": "sha512-K3PQ8utnVXXBCa5IRXRAhk/m83fNIsK77gTSXqAmPJe8eDTaSY1nifAOWPUmQDjzuCxYfa14UjGftHR9MFV70Q==", "integrity": "sha512-K3PQ8utnVXXBCa5IRXRAhk/m83fNIsK77gTSXqAmPJe8eDTaSY1nifAOWPUmQDjzuCxYfa14UjGftHR9MFV70Q==",
"requires": { "requires": {
"lodash-es": "^4.17.21" "lodash-es": "^4.17.21",
"viewerjs": "^1.11.6"
} }
}, },
"v8-compile-cache": { "v8-compile-cache": {
@ -29630,8 +29632,7 @@
"viewerjs": { "viewerjs": {
"version": "1.11.6", "version": "1.11.6",
"resolved": "https://registry.npmjs.org/viewerjs/-/viewerjs-1.11.6.tgz", "resolved": "https://registry.npmjs.org/viewerjs/-/viewerjs-1.11.6.tgz",
"integrity": "sha512-TlhdSp2oEOLFXvEp4psKaeTjR5zBjTRcM/sHUN8PkV1UWuY8HKC8n7GaVdW5Xqnwdr/F1OmzLik1QwDjI4w/nw==", "integrity": "sha512-TlhdSp2oEOLFXvEp4psKaeTjR5zBjTRcM/sHUN8PkV1UWuY8HKC8n7GaVdW5Xqnwdr/F1OmzLik1QwDjI4w/nw=="
"peer": true
}, },
"vm-browserify": { "vm-browserify": {
"version": "1.1.2", "version": "1.1.2",

View File

@ -1,53 +1,81 @@
const express = require('express') const express = require('express')
const axios = require('axios') const axios = require('axios')
const net = require('net')
const port = 3456 const port = 3456
// 起个服务 const isPortUsed = port => {
const app = express() return new Promise(resolve => {
app.use(express.json()) const server = net.createServer()
app.use(express.urlencoded({ extended: true })) server.once('error', err => {
if (err.code === 'EADDRINUSE') {
// 允许跨域 resolve(true) // 端口被占用
app.use((req, res, next) => { } else {
res.header('Access-Control-Allow-Origin', '*') // 允许所有来源的跨域请求,或者指定一个域名 resolve(false) // 其他错误
res.header('Access-Control-Allow-Methods', '*') // 允许的方法 }
res.header('Access-Control-Allow-Headers', '*') // 允许的头部信息
next()
})
// 监听对话请求
app.get('/ai/test', (req, res) => {
res
.json({
code: 0,
data: null,
msg: '连接成功'
}) })
.end() server.once('listening', () => {
}) server.close(() => resolve(false)) // 端口可用
app.post('/ai/chat', async (req, res, next) => {
// 设置SSE响应头
res.setHeader('Content-Type', 'text/event-stream')
res.setHeader('Cache-Control', 'no-cache')
res.setHeader('Connection', 'keep-alive')
const { api, method = 'POST', headers = {}, data } = req.body
try {
const response = await axios({
url: api,
method,
headers,
data,
responseType: 'stream'
}) })
response.data.pipe(res) server.listen(port) // 尝试监听端口
} catch (error) { })
next(error) }
const createServe = () => {
// 起个服务
const app = express()
app.use(express.json())
app.use(express.urlencoded({ extended: true }))
// 允许跨域
app.use((req, res, next) => {
res.header('Access-Control-Allow-Origin', '*') // 允许所有来源的跨域请求,或者指定一个域名
res.header('Access-Control-Allow-Methods', '*') // 允许的方法
res.header('Access-Control-Allow-Headers', '*') // 允许的头部信息
next()
})
// 监听对话请求
app.get('/ai/test', (req, res) => {
res
.json({
code: 0,
data: null,
msg: '连接成功'
})
.end()
})
app.post('/ai/chat', async (req, res, next) => {
// 设置SSE响应头
res.setHeader('Content-Type', 'text/event-stream')
res.setHeader('Cache-Control', 'no-cache')
res.setHeader('Connection', 'keep-alive')
const { api, method = 'POST', headers = {}, data } = req.body
try {
const response = await axios({
url: api,
method,
headers,
data,
responseType: 'stream'
})
response.data.pipe(res)
} catch (error) {
next(error)
}
})
app.listen(port, () => {
console.log(`app listening on port ${port}`)
})
}
isPortUsed(port).then(isUsed => {
if (isUsed) {
console.error('端口被占用')
} else {
createServe()
} }
}) })
app.listen(port, () => {
console.log(`app listening on port ${port}`)
})