diff --git a/simple-mind-map/src/plugins/RichText.js b/simple-mind-map/src/plugins/RichText.js
index 433d2a71..4f9c690a 100644
--- a/simple-mind-map/src/plugins/RichText.js
+++ b/simple-mind-map/src/plugins/RichText.js
@@ -820,6 +820,7 @@ class RichText {
// 处理导入数据
handleSetData(data) {
+ if (!data) return
// 短期处理,为了兼容老数据,长期会去除
const isOldRichTextVersion =
!data.smmVersion || compareVersion(data.smmVersion, '0.13.0') === '<'
diff --git a/simple-mind-map/src/utils/index.js b/simple-mind-map/src/utils/index.js
index 94d42aab..b3524ad8 100644
--- a/simple-mind-map/src/utils/index.js
+++ b/simple-mind-map/src/utils/index.js
@@ -398,7 +398,7 @@ export const nextTick = function (fn, ctx) {
}
// 检查节点是否超出画布
-export const checkNodeOuter = (mindMap, node) => {
+export const checkNodeOuter = (mindMap, node, offsetX = 0, offsetY = 0) => {
let elRect = mindMap.elRect
let { scaleX, scaleY, translateX, translateY } = mindMap.draw.transform()
let { left, top, width, height } = node
@@ -408,17 +408,17 @@ export const checkNodeOuter = (mindMap, node) => {
top = top * scaleY + translateY
let offsetLeft = 0
let offsetTop = 0
- if (left < 0) {
- offsetLeft = -left
+ if (left < 0 + offsetX) {
+ offsetLeft = -left + offsetX
}
- if (right > elRect.width) {
- offsetLeft = -(right - elRect.width)
+ if (right > elRect.width - offsetX) {
+ offsetLeft = -(right - elRect.width) - offsetX
}
- if (top < 0) {
- offsetTop = -top
+ if (top < 0 + offsetY) {
+ offsetTop = -top + offsetY
}
- if (bottom > elRect.height) {
- offsetTop = -(bottom - elRect.height)
+ if (bottom > elRect.height - offsetY) {
+ offsetTop = -(bottom - elRect.height) - offsetY
}
return {
isOuter: offsetLeft !== 0 || offsetTop !== 0,
@@ -508,7 +508,7 @@ export const loadImage = imgFile => {
// 移除字符串中的html实体
export const removeHTMLEntities = str => {
- ;[[' ', ' ']].forEach(item => {
+ [[' ', ' ']].forEach(item => {
str = str.replace(new RegExp(item[0], 'g'), item[1])
})
return str
@@ -1069,7 +1069,7 @@ export const generateColorByContent = str => {
// html转义
export const htmlEscape = str => {
- ;[
+ [
['&', '&'],
['<', '<'],
['>', '>']
diff --git a/web/package-lock.json b/web/package-lock.json
index 0e5e0d2e..e84cb3c7 100644
--- a/web/package-lock.json
+++ b/web/package-lock.json
@@ -31,6 +31,7 @@
"esbuild": "^0.17.15",
"eslint": "^6.7.2",
"eslint-plugin-vue": "^6.2.2",
+ "express": "^4.21.2",
"less": "^3.12.2",
"less-loader": "^7.1.0",
"markdown-it": "^13.0.1",
@@ -4161,9 +4162,9 @@
"dev": true
},
"node_modules/body-parser": {
- "version": "1.20.2",
- "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz",
- "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==",
+ "version": "1.20.3",
+ "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz",
+ "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==",
"dev": true,
"dependencies": {
"bytes": "3.1.2",
@@ -4174,7 +4175,7 @@
"http-errors": "2.0.0",
"iconv-lite": "0.4.24",
"on-finished": "2.4.1",
- "qs": "6.11.0",
+ "qs": "6.13.0",
"raw-body": "2.5.2",
"type-is": "~1.6.18",
"unpipe": "1.0.0"
@@ -4200,12 +4201,12 @@
"dev": true
},
"node_modules/body-parser/node_modules/qs": {
- "version": "6.11.0",
- "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz",
- "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==",
+ "version": "6.13.0",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz",
+ "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==",
"dev": true,
"dependencies": {
- "side-channel": "^1.0.4"
+ "side-channel": "^1.0.6"
},
"engines": {
"node": ">=0.6"
@@ -5240,9 +5241,9 @@
"dev": true
},
"node_modules/cookie": {
- "version": "0.5.0",
- "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz",
- "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==",
+ "version": "0.7.1",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz",
+ "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==",
"dev": true,
"engines": {
"node": ">= 0.6"
@@ -6623,9 +6624,9 @@
}
},
"node_modules/encodeurl": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
- "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==",
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz",
+ "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==",
"dev": true,
"engines": {
"node": ">= 0.8"
@@ -7353,37 +7354,37 @@
"dev": true
},
"node_modules/express": {
- "version": "4.18.3",
- "resolved": "https://registry.npmjs.org/express/-/express-4.18.3.tgz",
- "integrity": "sha512-6VyCijWQ+9O7WuVMTRBTl+cjNNIzD5cY5mQ1WM8r/LEkI2u8EYpOotESNwzNlyCn3g+dmjKYI6BmNneSr/FSRw==",
+ "version": "4.21.2",
+ "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz",
+ "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==",
"dev": true,
"dependencies": {
"accepts": "~1.3.8",
"array-flatten": "1.1.1",
- "body-parser": "1.20.2",
+ "body-parser": "1.20.3",
"content-disposition": "0.5.4",
"content-type": "~1.0.4",
- "cookie": "0.5.0",
+ "cookie": "0.7.1",
"cookie-signature": "1.0.6",
"debug": "2.6.9",
"depd": "2.0.0",
- "encodeurl": "~1.0.2",
+ "encodeurl": "~2.0.0",
"escape-html": "~1.0.3",
"etag": "~1.8.1",
- "finalhandler": "1.2.0",
+ "finalhandler": "1.3.1",
"fresh": "0.5.2",
"http-errors": "2.0.0",
- "merge-descriptors": "1.0.1",
+ "merge-descriptors": "1.0.3",
"methods": "~1.1.2",
"on-finished": "2.4.1",
"parseurl": "~1.3.3",
- "path-to-regexp": "0.1.7",
+ "path-to-regexp": "0.1.12",
"proxy-addr": "~2.0.7",
- "qs": "6.11.0",
+ "qs": "6.13.0",
"range-parser": "~1.2.1",
"safe-buffer": "5.2.1",
- "send": "0.18.0",
- "serve-static": "1.15.0",
+ "send": "0.19.0",
+ "serve-static": "1.16.2",
"setprototypeof": "1.2.0",
"statuses": "2.0.1",
"type-is": "~1.6.18",
@@ -7392,6 +7393,10 @@
},
"engines": {
"node": ">= 0.10.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
}
},
"node_modules/express/node_modules/debug": {
@@ -7410,12 +7415,12 @@
"dev": true
},
"node_modules/express/node_modules/qs": {
- "version": "6.11.0",
- "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz",
- "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==",
+ "version": "6.13.0",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz",
+ "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==",
"dev": true,
"dependencies": {
- "side-channel": "^1.0.4"
+ "side-channel": "^1.0.6"
},
"engines": {
"node": ">=0.6"
@@ -7712,13 +7717,13 @@
}
},
"node_modules/finalhandler": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz",
- "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==",
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz",
+ "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==",
"dev": true,
"dependencies": {
"debug": "2.6.9",
- "encodeurl": "~1.0.2",
+ "encodeurl": "~2.0.0",
"escape-html": "~1.0.3",
"on-finished": "2.4.1",
"parseurl": "~1.3.3",
@@ -10253,10 +10258,13 @@
}
},
"node_modules/merge-descriptors": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
- "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==",
- "dev": true
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz",
+ "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==",
+ "dev": true,
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
},
"node_modules/merge-source-map": {
"version": "1.1.0",
@@ -11572,9 +11580,9 @@
"dev": true
},
"node_modules/path-to-regexp": {
- "version": "0.1.7",
- "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
- "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==",
+ "version": "0.1.12",
+ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz",
+ "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==",
"dev": true
},
"node_modules/path-type": {
@@ -13295,9 +13303,9 @@
}
},
"node_modules/send": {
- "version": "0.18.0",
- "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz",
- "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==",
+ "version": "0.19.0",
+ "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz",
+ "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==",
"dev": true,
"dependencies": {
"debug": "2.6.9",
@@ -13333,6 +13341,15 @@
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
"dev": true
},
+ "node_modules/send/node_modules/encodeurl": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
+ "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
"node_modules/send/node_modules/ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
@@ -13427,15 +13444,15 @@
}
},
"node_modules/serve-static": {
- "version": "1.15.0",
- "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz",
- "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==",
+ "version": "1.16.2",
+ "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz",
+ "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==",
"dev": true,
"dependencies": {
- "encodeurl": "~1.0.2",
+ "encodeurl": "~2.0.0",
"escape-html": "~1.0.3",
"parseurl": "~1.3.3",
- "send": "0.18.0"
+ "send": "0.19.0"
},
"engines": {
"node": ">= 0.8.0"
@@ -20333,9 +20350,9 @@
"dev": true
},
"body-parser": {
- "version": "1.20.2",
- "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz",
- "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==",
+ "version": "1.20.3",
+ "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz",
+ "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==",
"dev": true,
"requires": {
"bytes": "3.1.2",
@@ -20346,7 +20363,7 @@
"http-errors": "2.0.0",
"iconv-lite": "0.4.24",
"on-finished": "2.4.1",
- "qs": "6.11.0",
+ "qs": "6.13.0",
"raw-body": "2.5.2",
"type-is": "~1.6.18",
"unpipe": "1.0.0"
@@ -20368,12 +20385,12 @@
"dev": true
},
"qs": {
- "version": "6.11.0",
- "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz",
- "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==",
+ "version": "6.13.0",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz",
+ "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==",
"dev": true,
"requires": {
- "side-channel": "^1.0.4"
+ "side-channel": "^1.0.6"
}
}
}
@@ -21195,9 +21212,9 @@
"dev": true
},
"cookie": {
- "version": "0.5.0",
- "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz",
- "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==",
+ "version": "0.7.1",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz",
+ "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==",
"dev": true
},
"cookie-signature": {
@@ -22285,9 +22302,9 @@
"dev": true
},
"encodeurl": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
- "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==",
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz",
+ "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==",
"dev": true
},
"end-of-stream": {
@@ -22857,37 +22874,37 @@
}
},
"express": {
- "version": "4.18.3",
- "resolved": "https://registry.npmjs.org/express/-/express-4.18.3.tgz",
- "integrity": "sha512-6VyCijWQ+9O7WuVMTRBTl+cjNNIzD5cY5mQ1WM8r/LEkI2u8EYpOotESNwzNlyCn3g+dmjKYI6BmNneSr/FSRw==",
+ "version": "4.21.2",
+ "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz",
+ "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==",
"dev": true,
"requires": {
"accepts": "~1.3.8",
"array-flatten": "1.1.1",
- "body-parser": "1.20.2",
+ "body-parser": "1.20.3",
"content-disposition": "0.5.4",
"content-type": "~1.0.4",
- "cookie": "0.5.0",
+ "cookie": "0.7.1",
"cookie-signature": "1.0.6",
"debug": "2.6.9",
"depd": "2.0.0",
- "encodeurl": "~1.0.2",
+ "encodeurl": "~2.0.0",
"escape-html": "~1.0.3",
"etag": "~1.8.1",
- "finalhandler": "1.2.0",
+ "finalhandler": "1.3.1",
"fresh": "0.5.2",
"http-errors": "2.0.0",
- "merge-descriptors": "1.0.1",
+ "merge-descriptors": "1.0.3",
"methods": "~1.1.2",
"on-finished": "2.4.1",
"parseurl": "~1.3.3",
- "path-to-regexp": "0.1.7",
+ "path-to-regexp": "0.1.12",
"proxy-addr": "~2.0.7",
- "qs": "6.11.0",
+ "qs": "6.13.0",
"range-parser": "~1.2.1",
"safe-buffer": "5.2.1",
- "send": "0.18.0",
- "serve-static": "1.15.0",
+ "send": "0.19.0",
+ "serve-static": "1.16.2",
"setprototypeof": "1.2.0",
"statuses": "2.0.1",
"type-is": "~1.6.18",
@@ -22911,12 +22928,12 @@
"dev": true
},
"qs": {
- "version": "6.11.0",
- "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz",
- "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==",
+ "version": "6.13.0",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz",
+ "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==",
"dev": true,
"requires": {
- "side-channel": "^1.0.4"
+ "side-channel": "^1.0.6"
}
},
"safe-buffer": {
@@ -23145,13 +23162,13 @@
}
},
"finalhandler": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz",
- "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==",
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz",
+ "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==",
"dev": true,
"requires": {
"debug": "2.6.9",
- "encodeurl": "~1.0.2",
+ "encodeurl": "~2.0.0",
"escape-html": "~1.0.3",
"on-finished": "2.4.1",
"parseurl": "~1.3.3",
@@ -25081,9 +25098,9 @@
}
},
"merge-descriptors": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
- "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==",
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz",
+ "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==",
"dev": true
},
"merge-source-map": {
@@ -26137,9 +26154,9 @@
"dev": true
},
"path-to-regexp": {
- "version": "0.1.7",
- "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
- "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==",
+ "version": "0.1.12",
+ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz",
+ "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==",
"dev": true
},
"path-type": {
@@ -27595,9 +27612,9 @@
"dev": true
},
"send": {
- "version": "0.18.0",
- "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz",
- "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==",
+ "version": "0.19.0",
+ "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz",
+ "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==",
"dev": true,
"requires": {
"debug": "2.6.9",
@@ -27632,6 +27649,12 @@
}
}
},
+ "encodeurl": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
+ "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==",
+ "dev": true
+ },
"ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
@@ -27718,15 +27741,15 @@
}
},
"serve-static": {
- "version": "1.15.0",
- "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz",
- "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==",
+ "version": "1.16.2",
+ "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz",
+ "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==",
"dev": true,
"requires": {
- "encodeurl": "~1.0.2",
+ "encodeurl": "~2.0.0",
"escape-html": "~1.0.3",
"parseurl": "~1.3.3",
- "send": "0.18.0"
+ "send": "0.19.0"
}
},
"set-blocking": {
diff --git a/web/package.json b/web/package.json
index 7a4101e4..c145d173 100644
--- a/web/package.json
+++ b/web/package.json
@@ -8,7 +8,8 @@
"lint": "vue-cli-service lint",
"buildLibrary": "node ./scripts/updateVersion.js && vue-cli-service build --mode library --target lib --name simpleMindMap ../simple-mind-map/full.js --dest ../simple-mind-map/dist && esbuild ../simple-mind-map/full.js --bundle --external:buffer --format=esm --outfile=../simple-mind-map/dist/simpleMindMap.esm.js && esbuild ../simple-mind-map/full.js --bundle --minify --external:buffer --format=esm --outfile=../simple-mind-map/dist/simpleMindMap.esm.min.js",
"format": "prettier --write src/* src/*/* src/*/*/* src/*/*/*/*",
- "createNodeImageList": "node ./scripts/createNodeImageList.js"
+ "createNodeImageList": "node ./scripts/createNodeImageList.js",
+ "ai:serve": "node ./scripts/ai.js"
},
"dependencies": {
"@toast-ui/editor": "^3.1.5",
@@ -34,6 +35,7 @@
"esbuild": "^0.17.15",
"eslint": "^6.7.2",
"eslint-plugin-vue": "^6.2.2",
+ "express": "^4.21.2",
"less": "^3.12.2",
"less-loader": "^7.1.0",
"markdown-it": "^13.0.1",
diff --git a/web/scripts/ai.js b/web/scripts/ai.js
new file mode 100644
index 00000000..67eb6f7e
--- /dev/null
+++ b/web/scripts/ai.js
@@ -0,0 +1,108 @@
+const express = require('express')
+const http = require('http')
+const { pipeline } = require('stream')
+
+const port = 3456
+
+// 起个服务
+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', (req, res) => {
+ // 设置SSE响应头
+ res.setHeader('Content-Type', 'text/event-stream')
+ res.setHeader('Cache-Control', 'no-cache')
+ res.setHeader('Connection', 'keep-alive')
+
+ const { api, method, headers, data } = req.body
+
+ // 创建代理请求
+ const proxyReq = http.request(
+ api,
+ {
+ method: method || 'POST',
+ headers: {
+ ...headers
+ }
+ },
+ proxyRes => {
+ // 检查目标服务响应状态
+ if (proxyRes.statusCode !== 200) {
+ proxyRes.resume()
+ return res.status(proxyRes.statusCode).end()
+ }
+
+ // 使用双向流管道
+ const pipelinePromise = new Promise(resolve => {
+ pipeline(proxyRes, res, err => {
+ // 过滤客户端主动断开的情况
+ if (err && err.code !== 'ERR_STREAM_PREMATURE_CLOSE') {
+ console.error('Pipeline error:', err)
+ }
+ resolve()
+ })
+ })
+
+ // 处理流结束
+ proxyRes.on('end', () => {
+ if (!res.writableEnded) {
+ res.end()
+ }
+ })
+
+ return pipelinePromise
+ }
+ )
+
+ // 错误处理增强
+ const handleError = err => {
+ if (!res.headersSent) {
+ res.status(502).end('Bad Gateway')
+ }
+ cleanupStreams()
+ }
+
+ // 流清理函数
+ const cleanupStreams = () => {
+ proxyReq.destroy()
+ res.destroy()
+ }
+
+ // 事件监听器
+ proxyReq.on('error', handleError)
+ res.on('error', handleError)
+
+ // 处理客户端提前断开
+ req.on('close', () => {
+ if (!res.writableFinished) {
+ console.log('Client disconnected prematurely')
+ cleanupStreams()
+ }
+ })
+
+ proxyReq.write(JSON.stringify(data))
+ proxyReq.end()
+})
+
+app.listen(port, () => {
+ console.log(`app listening on port ${port}`)
+})
diff --git a/web/src/assets/icon-font/iconfont.css b/web/src/assets/icon-font/iconfont.css
index 2e741b11..71be3af5 100644
--- a/web/src/assets/icon-font/iconfont.css
+++ b/web/src/assets/icon-font/iconfont.css
@@ -1,8 +1,8 @@
@font-face {
font-family: "iconfont"; /* Project id 2479351 */
- src: url('iconfont.woff2?t=1739152990179') format('woff2'),
- url('iconfont.woff?t=1739152990179') format('woff'),
- url('iconfont.ttf?t=1739152990179') format('truetype');
+ src: url('iconfont.woff2?t=1739843331607') format('woff2'),
+ url('iconfont.woff?t=1739843331607') format('woff'),
+ url('iconfont.ttf?t=1739843331607') format('truetype');
}
.iconfont {
@@ -13,6 +13,10 @@
-moz-osx-font-smoothing: grayscale;
}
+.iconAIshengcheng:before {
+ content: "\e6b5";
+}
+
.iconprinting:before {
content: "\ea28";
}
diff --git a/web/src/assets/icon-font/iconfont.ttf b/web/src/assets/icon-font/iconfont.ttf
index 06a6deea..f8154868 100644
Binary files a/web/src/assets/icon-font/iconfont.ttf and b/web/src/assets/icon-font/iconfont.ttf differ
diff --git a/web/src/assets/icon-font/iconfont.woff b/web/src/assets/icon-font/iconfont.woff
index b98983ec..c9ebb1e3 100644
Binary files a/web/src/assets/icon-font/iconfont.woff and b/web/src/assets/icon-font/iconfont.woff differ
diff --git a/web/src/assets/icon-font/iconfont.woff2 b/web/src/assets/icon-font/iconfont.woff2
index 09818b06..16588279 100644
Binary files a/web/src/assets/icon-font/iconfont.woff2 and b/web/src/assets/icon-font/iconfont.woff2 differ
diff --git a/web/src/config/en.js b/web/src/config/en.js
index dae1310f..1f3a3755 100644
--- a/web/src/config/en.js
+++ b/web/src/config/en.js
@@ -444,6 +444,11 @@ export const sidebarTriggerList = [
value: 'setting',
icon: 'iconshezhi'
},
+ {
+ name: 'AI',
+ value: 'ai',
+ icon: 'iconAIshengcheng'
+ },
{
name: 'ShortcutKey',
value: 'shortcutKey',
diff --git a/web/src/config/zh.js b/web/src/config/zh.js
index 75793ad9..3813a5e4 100644
--- a/web/src/config/zh.js
+++ b/web/src/config/zh.js
@@ -534,6 +534,11 @@ export const sidebarTriggerList = [
value: 'outline',
icon: 'iconfuhao-dagangshu'
},
+ {
+ name: 'AI',
+ value: 'ai',
+ icon: 'iconAIshengcheng'
+ },
{
name: '设置',
value: 'setting',
diff --git a/web/src/config/zhtw.js b/web/src/config/zhtw.js
index 56dff3d1..106441f7 100644
--- a/web/src/config/zhtw.js
+++ b/web/src/config/zhtw.js
@@ -439,6 +439,11 @@ export const sidebarTriggerList = [
value: 'outline',
icon: 'iconfuhao-dagangshu'
},
+ {
+ name: 'AI',
+ value: 'ai',
+ icon: 'iconAIshengcheng'
+ },
{
name: '設置',
value: 'setting',
diff --git a/web/src/lang/en_us.js b/web/src/lang/en_us.js
index fbabd0cf..6d856a22 100644
--- a/web/src/lang/en_us.js
+++ b/web/src/lang/en_us.js
@@ -134,7 +134,8 @@ export default {
expandNodeChild: 'Expand all sub nodes',
unExpandNodeChild: 'Un expand all sub nodes',
addToDo: 'Add toDo',
- removeToDo: 'Remove toDo'
+ removeToDo: 'Remove toDo',
+ aiCreate: 'AI Continuation'
},
count: {
words: 'Words',
@@ -329,7 +330,8 @@ export default {
newFileTip:
'Please export the currently edited file before creating a new one, Beware of content loss',
openFileTip:
- 'Please export the currently edited file before opening it, Beware of content loss'
+ 'Please export the currently edited file before opening it, Beware of content loss',
+ ai: 'AI'
},
edit: {
newFeatureNoticeTitle: 'New feature reminder',
diff --git a/web/src/lang/zh_cn.js b/web/src/lang/zh_cn.js
index d4b58234..9262cb13 100644
--- a/web/src/lang/zh_cn.js
+++ b/web/src/lang/zh_cn.js
@@ -133,7 +133,8 @@ export default {
expandNodeChild: '展开所有下级节点',
unExpandNodeChild: '收起所有下级节点',
addToDo: '添加待办',
- removeToDo: '删除待办'
+ removeToDo: '删除待办',
+ aiCreate: 'AI续写'
},
count: {
words: '字数',
@@ -323,7 +324,8 @@ export default {
creatingTip: '正在创建文件',
directory: '目录',
newFileTip: '新建文件前请先导出当前编辑的文件,谨防内容丢失',
- openFileTip: '打开文件前请先导出当前编辑的文件,谨防内容丢失'
+ openFileTip: '打开文件前请先导出当前编辑的文件,谨防内容丢失',
+ ai: 'AI'
},
edit: {
newFeatureNoticeTitle: '新特性提醒',
@@ -412,5 +414,8 @@ export default {
nodeTagStyle: {
placeholder: '请输入标签内容',
delete: '删除此标签'
+ },
+ ai: {
+ chatTitle: 'AI对话'
}
}
diff --git a/web/src/lang/zh_tw.js b/web/src/lang/zh_tw.js
index a22f76d8..2bb41eb2 100644
--- a/web/src/lang/zh_tw.js
+++ b/web/src/lang/zh_tw.js
@@ -134,7 +134,8 @@ export default {
expandNodeChild: '展開所有下級節點',
unExpandNodeChild: '收起所有下級節點',
addToDo: '添加待辦',
- removeToDo: '刪除待辦'
+ removeToDo: '刪除待辦',
+ aiCreate: 'AI續寫'
},
count: {
words: '字數',
@@ -323,7 +324,8 @@ export default {
creatingTip: '正在建立檔案',
directory: '目錄',
newFileTip: '新增檔案前,請先匯出目前編輯的檔案,以免內容遺失',
- openFileTip: '開啟檔案前,請先匯出目前編輯的檔案,以免內容遺失'
+ openFileTip: '開啟檔案前,請先匯出目前編輯的檔案,以免內容遺失',
+ ai: 'AI'
},
edit: {
newFeatureNoticeTitle: '新功能提醒',
diff --git a/web/src/main.js b/web/src/main.js
index 22261c40..cbdb93bd 100644
--- a/web/src/main.js
+++ b/web/src/main.js
@@ -35,4 +35,3 @@ if (window.takeOverApp) {
} else {
initApp()
}
-
diff --git a/web/src/pages/Edit/components/AiChat.vue b/web/src/pages/Edit/components/AiChat.vue
new file mode 100644
index 00000000..f1ad934d
--- /dev/null
+++ b/web/src/pages/Edit/components/AiChat.vue
@@ -0,0 +1,290 @@
+
+ 火山方舟大模型配置:
+ 目前仅支持火山方舟大模型,需要自行去获取key,详细操作步骤见:教程。
+ 思绪思维导图客户端配置: