解决不同标签页多余监听的问题

This commit is contained in:
锦恢 2025-04-08 15:10:45 +08:00
parent 36ee137dba
commit c026b17fdc
11 changed files with 549 additions and 4943 deletions

4786
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -9,8 +9,7 @@
"categories": [ "categories": [
"Other" "Other"
], ],
"activationEvents": [ "activationEvents": [],
],
"main": "./dist/extension.js", "main": "./dist/extension.js",
"contributes": { "contributes": {
"viewsContainers": { "viewsContainers": {
@ -32,5 +31,11 @@
} }
] ]
} }
},
"dependencies": {
},
"devDependencies": {
"@types/markdown-it": "^14.1.2"
} }
} }

View File

@ -10,6 +10,9 @@
"dependencies": { "dependencies": {
"core-js": "^3.8.3", "core-js": "^3.8.3",
"element-plus": "^2.9.7", "element-plus": "^2.9.7",
"katex": "^0.16.21",
"markdown-it": "^14.1.0",
"markdown-it-katex": "^2.0.3",
"vue": "^3.2.13", "vue": "^3.2.13",
"vue-i18n": "^11.1.0", "vue-i18n": "^11.1.0",
"vue-router": "^4.0.3" "vue-router": "^4.0.3"
@ -28,7 +31,7 @@
"eslint-plugin-prettier": "^4.0.0", "eslint-plugin-prettier": "^4.0.0",
"eslint-plugin-vue": "^8.0.3", "eslint-plugin-vue": "^8.0.3",
"prettier": "^2.4.1", "prettier": "^2.4.1",
"typescript": "~4.5.5", "typescript": "^5.9.0-dev.20250407",
"unplugin-auto-import": "^0.17.5", "unplugin-auto-import": "^0.17.5",
"unplugin-vue-components": "^0.26.0" "unplugin-vue-components": "^0.26.0"
} }
@ -2559,6 +2562,44 @@
"node": ">=10" "node": ">=10"
} }
}, },
"node_modules/@typescript-eslint/eslint-plugin/node_modules/tslib": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
"dev": true,
"license": "0BSD"
},
"node_modules/@typescript-eslint/eslint-plugin/node_modules/tsutils": {
"version": "3.21.0",
"resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz",
"integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==",
"dev": true,
"license": "MIT",
"dependencies": {
"tslib": "^1.8.1"
},
"engines": {
"node": ">= 6"
},
"peerDependencies": {
"typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta"
}
},
"node_modules/@typescript-eslint/eslint-plugin/node_modules/typescript": {
"version": "5.8.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz",
"integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==",
"dev": true,
"license": "Apache-2.0",
"peer": true,
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
},
"engines": {
"node": ">=14.17"
}
},
"node_modules/@typescript-eslint/parser": { "node_modules/@typescript-eslint/parser": {
"version": "5.62.0", "version": "5.62.0",
"resolved": "https://registry.npmmirror.com/@typescript-eslint/parser/-/parser-5.62.0.tgz", "resolved": "https://registry.npmmirror.com/@typescript-eslint/parser/-/parser-5.62.0.tgz",
@ -2633,6 +2674,44 @@
} }
} }
}, },
"node_modules/@typescript-eslint/type-utils/node_modules/tslib": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
"dev": true,
"license": "0BSD"
},
"node_modules/@typescript-eslint/type-utils/node_modules/tsutils": {
"version": "3.21.0",
"resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz",
"integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==",
"dev": true,
"license": "MIT",
"dependencies": {
"tslib": "^1.8.1"
},
"engines": {
"node": ">= 6"
},
"peerDependencies": {
"typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta"
}
},
"node_modules/@typescript-eslint/type-utils/node_modules/typescript": {
"version": "5.8.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz",
"integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==",
"dev": true,
"license": "Apache-2.0",
"peer": true,
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
},
"engines": {
"node": ">=14.17"
}
},
"node_modules/@typescript-eslint/types": { "node_modules/@typescript-eslint/types": {
"version": "5.62.0", "version": "5.62.0",
"resolved": "https://registry.npmmirror.com/@typescript-eslint/types/-/types-5.62.0.tgz", "resolved": "https://registry.npmmirror.com/@typescript-eslint/types/-/types-5.62.0.tgz",
@ -2688,6 +2767,44 @@
"node": ">=10" "node": ">=10"
} }
}, },
"node_modules/@typescript-eslint/typescript-estree/node_modules/tslib": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
"dev": true,
"license": "0BSD"
},
"node_modules/@typescript-eslint/typescript-estree/node_modules/tsutils": {
"version": "3.21.0",
"resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz",
"integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==",
"dev": true,
"license": "MIT",
"dependencies": {
"tslib": "^1.8.1"
},
"engines": {
"node": ">= 6"
},
"peerDependencies": {
"typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta"
}
},
"node_modules/@typescript-eslint/typescript-estree/node_modules/typescript": {
"version": "5.8.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz",
"integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==",
"dev": true,
"license": "Apache-2.0",
"peer": true,
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
},
"engines": {
"node": ">=14.17"
}
},
"node_modules/@typescript-eslint/utils": { "node_modules/@typescript-eslint/utils": {
"version": "5.62.0", "version": "5.62.0",
"resolved": "https://registry.npmmirror.com/@typescript-eslint/utils/-/utils-5.62.0.tgz", "resolved": "https://registry.npmmirror.com/@typescript-eslint/utils/-/utils-5.62.0.tgz",
@ -3075,6 +3192,95 @@
} }
} }
}, },
"node_modules/@vue/cli-plugin-typescript/node_modules/chalk": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
"dev": true,
"license": "MIT",
"dependencies": {
"ansi-styles": "^4.1.0",
"supports-color": "^7.1.0"
},
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/chalk/chalk?sponsor=1"
}
},
"node_modules/@vue/cli-plugin-typescript/node_modules/fork-ts-checker-webpack-plugin": {
"version": "6.5.3",
"resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-6.5.3.tgz",
"integrity": "sha512-SbH/l9ikmMWycd5puHJKTkZJKddF4iRLyW3DeZ08HTI7NGyLS38MXd/KGgeWumQO7YNQbW2u/NtPT2YowbPaGQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@babel/code-frame": "^7.8.3",
"@types/json-schema": "^7.0.5",
"chalk": "^4.1.0",
"chokidar": "^3.4.2",
"cosmiconfig": "^6.0.0",
"deepmerge": "^4.2.2",
"fs-extra": "^9.0.0",
"glob": "^7.1.6",
"memfs": "^3.1.2",
"minimatch": "^3.0.4",
"schema-utils": "2.7.0",
"semver": "^7.3.2",
"tapable": "^1.0.0"
},
"engines": {
"node": ">=10",
"yarn": ">=1.0.0"
},
"peerDependencies": {
"eslint": ">= 6",
"typescript": ">= 2.7",
"vue-template-compiler": "*",
"webpack": ">= 4"
},
"peerDependenciesMeta": {
"eslint": {
"optional": true
},
"vue-template-compiler": {
"optional": true
}
}
},
"node_modules/@vue/cli-plugin-typescript/node_modules/schema-utils": {
"version": "2.7.0",
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.0.tgz",
"integrity": "sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A==",
"dev": true,
"license": "MIT",
"dependencies": {
"@types/json-schema": "^7.0.4",
"ajv": "^6.12.2",
"ajv-keywords": "^3.4.1"
},
"engines": {
"node": ">= 8.9.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/webpack"
}
},
"node_modules/@vue/cli-plugin-typescript/node_modules/semver": {
"version": "7.7.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz",
"integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==",
"dev": true,
"license": "ISC",
"bin": {
"semver": "bin/semver.js"
},
"engines": {
"node": ">=10"
}
},
"node_modules/@vue/cli-plugin-vuex": { "node_modules/@vue/cli-plugin-vuex": {
"version": "5.0.8", "version": "5.0.8",
"resolved": "https://registry.npmmirror.com/@vue/cli-plugin-vuex/-/cli-plugin-vuex-5.0.8.tgz", "resolved": "https://registry.npmmirror.com/@vue/cli-plugin-vuex/-/cli-plugin-vuex-5.0.8.tgz",
@ -4781,7 +4987,6 @@
"version": "8.3.0", "version": "8.3.0",
"resolved": "https://registry.npmmirror.com/commander/-/commander-8.3.0.tgz", "resolved": "https://registry.npmmirror.com/commander/-/commander-8.3.0.tgz",
"integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==",
"dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">= 12" "node": ">= 12"
@ -5006,7 +5211,7 @@
}, },
"node_modules/cosmiconfig": { "node_modules/cosmiconfig": {
"version": "6.0.0", "version": "6.0.0",
"resolved": "https://registry.npmmirror.com/cosmiconfig/-/cosmiconfig-6.0.0.tgz", "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz",
"integrity": "sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==", "integrity": "sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
@ -5401,7 +5606,7 @@
}, },
"node_modules/deepmerge": { "node_modules/deepmerge": {
"version": "4.3.1", "version": "4.3.1",
"resolved": "https://registry.npmmirror.com/deepmerge/-/deepmerge-4.3.1.tgz", "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz",
"integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
@ -7038,95 +7243,6 @@
} }
} }
}, },
"node_modules/fork-ts-checker-webpack-plugin": {
"version": "6.5.3",
"resolved": "https://registry.npmmirror.com/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-6.5.3.tgz",
"integrity": "sha512-SbH/l9ikmMWycd5puHJKTkZJKddF4iRLyW3DeZ08HTI7NGyLS38MXd/KGgeWumQO7YNQbW2u/NtPT2YowbPaGQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@babel/code-frame": "^7.8.3",
"@types/json-schema": "^7.0.5",
"chalk": "^4.1.0",
"chokidar": "^3.4.2",
"cosmiconfig": "^6.0.0",
"deepmerge": "^4.2.2",
"fs-extra": "^9.0.0",
"glob": "^7.1.6",
"memfs": "^3.1.2",
"minimatch": "^3.0.4",
"schema-utils": "2.7.0",
"semver": "^7.3.2",
"tapable": "^1.0.0"
},
"engines": {
"node": ">=10",
"yarn": ">=1.0.0"
},
"peerDependencies": {
"eslint": ">= 6",
"typescript": ">= 2.7",
"vue-template-compiler": "*",
"webpack": ">= 4"
},
"peerDependenciesMeta": {
"eslint": {
"optional": true
},
"vue-template-compiler": {
"optional": true
}
}
},
"node_modules/fork-ts-checker-webpack-plugin/node_modules/chalk": {
"version": "4.1.2",
"resolved": "https://registry.npmmirror.com/chalk/-/chalk-4.1.2.tgz",
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
"dev": true,
"license": "MIT",
"dependencies": {
"ansi-styles": "^4.1.0",
"supports-color": "^7.1.0"
},
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/chalk/chalk?sponsor=1"
}
},
"node_modules/fork-ts-checker-webpack-plugin/node_modules/schema-utils": {
"version": "2.7.0",
"resolved": "https://registry.npmmirror.com/schema-utils/-/schema-utils-2.7.0.tgz",
"integrity": "sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A==",
"dev": true,
"license": "MIT",
"dependencies": {
"@types/json-schema": "^7.0.4",
"ajv": "^6.12.2",
"ajv-keywords": "^3.4.1"
},
"engines": {
"node": ">= 8.9.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/webpack"
}
},
"node_modules/fork-ts-checker-webpack-plugin/node_modules/semver": {
"version": "7.7.1",
"resolved": "https://registry.npmmirror.com/semver/-/semver-7.7.1.tgz",
"integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==",
"dev": true,
"license": "ISC",
"bin": {
"semver": "bin/semver.js"
},
"engines": {
"node": ">=10"
}
},
"node_modules/forwarded": { "node_modules/forwarded": {
"version": "0.2.0", "version": "0.2.0",
"resolved": "https://registry.npmmirror.com/forwarded/-/forwarded-0.2.0.tgz", "resolved": "https://registry.npmmirror.com/forwarded/-/forwarded-0.2.0.tgz",
@ -8241,6 +8357,22 @@
"graceful-fs": "^4.1.6" "graceful-fs": "^4.1.6"
} }
}, },
"node_modules/katex": {
"version": "0.16.21",
"resolved": "https://registry.npmjs.org/katex/-/katex-0.16.21.tgz",
"integrity": "sha512-XvqR7FgOHtWupfMiigNzmh+MgUVmDGU2kXZm899ZkPfcuoPuFxyHmXsgATDpFZDAXCI8tvinaVcDo8PIIJSo4A==",
"funding": [
"https://opencollective.com/katex",
"https://github.com/sponsors/katex"
],
"license": "MIT",
"dependencies": {
"commander": "^8.3.0"
},
"bin": {
"katex": "cli.js"
}
},
"node_modules/keyv": { "node_modules/keyv": {
"version": "4.5.4", "version": "4.5.4",
"resolved": "https://registry.npmmirror.com/keyv/-/keyv-4.5.4.tgz", "resolved": "https://registry.npmmirror.com/keyv/-/keyv-4.5.4.tgz",
@ -8323,6 +8455,15 @@
"dev": true, "dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/linkify-it": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz",
"integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==",
"license": "MIT",
"dependencies": {
"uc.micro": "^2.0.0"
}
},
"node_modules/loader-runner": { "node_modules/loader-runner": {
"version": "4.3.0", "version": "4.3.0",
"resolved": "https://registry.npmmirror.com/loader-runner/-/loader-runner-4.3.0.tgz", "resolved": "https://registry.npmmirror.com/loader-runner/-/loader-runner-4.3.0.tgz",
@ -8675,6 +8816,55 @@
"url": "https://github.com/sponsors/sindresorhus" "url": "https://github.com/sponsors/sindresorhus"
} }
}, },
"node_modules/markdown-it": {
"version": "14.1.0",
"resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz",
"integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==",
"license": "MIT",
"dependencies": {
"argparse": "^2.0.1",
"entities": "^4.4.0",
"linkify-it": "^5.0.0",
"mdurl": "^2.0.0",
"punycode.js": "^2.3.1",
"uc.micro": "^2.1.0"
},
"bin": {
"markdown-it": "bin/markdown-it.mjs"
}
},
"node_modules/markdown-it-katex": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/markdown-it-katex/-/markdown-it-katex-2.0.3.tgz",
"integrity": "sha512-nUkkMtRWeg7OpdflamflE/Ho/pWl64Lk9wNBKOmaj33XkQdumhXAIYhI0WO03GeiycPCsxbmX536V5NEXpC3Ng==",
"license": "MIT",
"dependencies": {
"katex": "^0.6.0"
}
},
"node_modules/markdown-it-katex/node_modules/katex": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/katex/-/katex-0.6.0.tgz",
"integrity": "sha512-rS4mY3SvHYg5LtQV6RBcK0if7ur6plyEukAOV+jGGPqFImuzu8fHL6M752iBmRGoUyF0bhZbAPoezehn7xYksA==",
"license": "MIT",
"dependencies": {
"match-at": "^0.1.0"
},
"bin": {
"katex": "cli.js"
}
},
"node_modules/markdown-it/node_modules/argparse": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
"license": "Python-2.0"
},
"node_modules/match-at": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/match-at/-/match-at-0.1.1.tgz",
"integrity": "sha512-h4Yd392z9mST+dzc+yjuybOGFNOZjmXIPKWjxBd1Bb23r4SmDOsk2NYCU2BMUBGbSpZqwVsZYNq26QS3xfaT3Q=="
},
"node_modules/math-intrinsics": { "node_modules/math-intrinsics": {
"version": "1.1.0", "version": "1.1.0",
"resolved": "https://registry.npmmirror.com/math-intrinsics/-/math-intrinsics-1.1.0.tgz", "resolved": "https://registry.npmmirror.com/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
@ -8692,6 +8882,12 @@
"dev": true, "dev": true,
"license": "CC0-1.0" "license": "CC0-1.0"
}, },
"node_modules/mdurl": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz",
"integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==",
"license": "MIT"
},
"node_modules/media-typer": { "node_modules/media-typer": {
"version": "0.3.0", "version": "0.3.0",
"resolved": "https://registry.npmmirror.com/media-typer/-/media-typer-0.3.0.tgz", "resolved": "https://registry.npmmirror.com/media-typer/-/media-typer-0.3.0.tgz",
@ -10519,6 +10715,15 @@
"node": ">=6" "node": ">=6"
} }
}, },
"node_modules/punycode.js": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz",
"integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==",
"license": "MIT",
"engines": {
"node": ">=6"
}
},
"node_modules/qs": { "node_modules/qs": {
"version": "6.13.0", "version": "6.13.0",
"resolved": "https://registry.npmmirror.com/qs/-/qs-6.13.0.tgz", "resolved": "https://registry.npmmirror.com/qs/-/qs-6.13.0.tgz",
@ -11769,7 +11974,7 @@
}, },
"node_modules/tapable": { "node_modules/tapable": {
"version": "1.1.3", "version": "1.1.3",
"resolved": "https://registry.npmmirror.com/tapable/-/tapable-1.1.3.tgz", "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz",
"integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==", "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
@ -12098,29 +12303,6 @@
"dev": true, "dev": true,
"license": "0BSD" "license": "0BSD"
}, },
"node_modules/tsutils": {
"version": "3.21.0",
"resolved": "https://registry.npmmirror.com/tsutils/-/tsutils-3.21.0.tgz",
"integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==",
"dev": true,
"license": "MIT",
"dependencies": {
"tslib": "^1.8.1"
},
"engines": {
"node": ">= 6"
},
"peerDependencies": {
"typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta"
}
},
"node_modules/tsutils/node_modules/tslib": {
"version": "1.14.1",
"resolved": "https://registry.npmmirror.com/tslib/-/tslib-1.14.1.tgz",
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
"dev": true,
"license": "0BSD"
},
"node_modules/type-check": { "node_modules/type-check": {
"version": "0.4.0", "version": "0.4.0",
"resolved": "https://registry.npmmirror.com/type-check/-/type-check-0.4.0.tgz", "resolved": "https://registry.npmmirror.com/type-check/-/type-check-0.4.0.tgz",
@ -12159,9 +12341,9 @@
} }
}, },
"node_modules/typescript": { "node_modules/typescript": {
"version": "4.5.5", "version": "5.9.0-dev.20250407",
"resolved": "https://registry.npmmirror.com/typescript/-/typescript-4.5.5.tgz", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.0-dev.20250407.tgz",
"integrity": "sha512-TCTIul70LyWe6IJWT8QSYeA54WQe8EjQFU4wY52Fasj5UKx88LNYKCgBEHcOMOrFF1rKGbD8v/xcNWVUq9SymA==", "integrity": "sha512-JW8/Our6MR+QYS3M134UaLWtEYdVXWzwlbg6rj3fmF9TppADEdaSNiJK90M2wmfSuu5j8Nefk93oSrZF03JkGw==",
"devOptional": true, "devOptional": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"bin": { "bin": {
@ -12169,9 +12351,15 @@
"tsserver": "bin/tsserver" "tsserver": "bin/tsserver"
}, },
"engines": { "engines": {
"node": ">=4.2.0" "node": ">=14.17"
} }
}, },
"node_modules/uc.micro": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz",
"integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==",
"license": "MIT"
},
"node_modules/ufo": { "node_modules/ufo": {
"version": "1.5.4", "version": "1.5.4",
"resolved": "https://registry.npmjs.org/ufo/-/ufo-1.5.4.tgz", "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.5.4.tgz",

View File

@ -10,6 +10,9 @@
"dependencies": { "dependencies": {
"core-js": "^3.8.3", "core-js": "^3.8.3",
"element-plus": "^2.9.7", "element-plus": "^2.9.7",
"katex": "^0.16.21",
"markdown-it": "^14.1.0",
"markdown-it-katex": "^2.0.3",
"vue": "^3.2.13", "vue": "^3.2.13",
"vue-i18n": "^11.1.0", "vue-i18n": "^11.1.0",
"vue-router": "^4.0.3" "vue-router": "^4.0.3"
@ -28,7 +31,7 @@
"eslint-plugin-prettier": "^4.0.0", "eslint-plugin-prettier": "^4.0.0",
"eslint-plugin-vue": "^8.0.3", "eslint-plugin-vue": "^8.0.3",
"prettier": "^2.4.1", "prettier": "^2.4.1",
"typescript": "~4.5.5", "typescript": "^5.9.0-dev.20250407",
"unplugin-auto-import": "^0.17.5", "unplugin-auto-import": "^0.17.5",
"unplugin-vue-components": "^0.26.0" "unplugin-vue-components": "^0.26.0"
} }

View File

@ -6,7 +6,7 @@
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0"> <meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.svg"> <link rel="icon" href="<%= BASE_URL %>favicon.svg">
<link rel="stylesheet" href="default-dark.css"> <link rel="stylesheet" href="default-light.css">
<link rel="stylesheet" href="vscode.css"> <link rel="stylesheet" href="vscode.css">
<link rel="stylesheet" href="mcp.css"> <link rel="stylesheet" href="mcp.css">
<link rel="stylesheet" href="iconfont.css"> <link rel="stylesheet" href="iconfont.css">

View File

@ -2,16 +2,38 @@
<div class="chat-container" ref="chatContainerRef"> <div class="chat-container" ref="chatContainerRef">
<el-scrollbar :height="'90%'"> <el-scrollbar :height="'90%'">
<div class="message-list"> <div class="message-list">
<div v-for="(message, index) in messages" :key="index" :class="['message-item', message.role]"> <div v-for="(message, index) in tabStorage.messages" :key="index"
:class="['message-item', message.role]"
>
<div class="message-avatar" v-if="message.role === 'assistant'"> <div class="message-avatar" v-if="message.role === 'assistant'">
<span class="iconfont icon-chat"></span> <span class="iconfont icon-chat"></span>
</div> </div>
<div class="message-content">
<div class="message-role">{{ message.role === 'user' ? '' : 'Agent' }}</div> <!-- 用户输入的部分不需要渲染成 markdown -->
<div class="message-content" v-if="message.role === 'user'">
<div class="message-role"></div>
<div class="message-text"> <div class="message-text">
<span>{{ message.content }}</span> <span>{{ message.content }}</span>
</div> </div>
</div> </div>
<!-- 助手返回的部分 -->
<div class="message-content" v-else-if="message.role === 'assistant'">
<div class="message-role">Agent</div>
<div class="message-text">
<div v-html="markdownToHtml(message.content)" ref="markdownContent"></div>
<span class="iconfont icon-copy" @click="handleCopy(message.content)"></span>
</div>
</div>
<!-- 待定 -->
<div class="message-content" v-else>
<div class="message-role">Tool</div>
<div class="message-text">
<span>Tool</span>
</div>
</div>
</div> </div>
<div v-if="isLoading" class="message-item assistant"> <div v-if="isLoading" class="message-item assistant">
@ -59,6 +81,8 @@ import { ChatMessage, ChatStorage } from './chat';
import Setting from './setting.vue'; import Setting from './setting.vue';
import { llmManager, llms } from '@/views/setting/llm'; import { llmManager, llms } from '@/views/setting/llm';
// markdown.ts
import { markdownToHtml, copyToClipboard } from './markdown';
defineComponent({ name: 'chat' }); defineComponent({ name: 'chat' });
@ -85,7 +109,6 @@ const inputHeightLines = computed(() => {
if (!tabStorage.messages) { if (!tabStorage.messages) {
tabStorage.messages = [] as ChatMessage[]; tabStorage.messages = [] as ChatMessage[];
} }
const messages = tabStorage.messages;
const isLoading = ref(false); const isLoading = ref(false);
const streamingContent = ref(''); const streamingContent = ref('');
@ -109,11 +132,20 @@ const handleKeydown = (event: KeyboardEvent) => {
// Shift+Enter // Shift+Enter
}; };
const handleCopy = async (text: string) => {
try {
await copyToClipboard(text);
ElMessage.success('复制成功');
} catch (error) {
ElMessage.error('复制失败: ' + error);
}
};
const handleSend = () => { const handleSend = () => {
if (!userInput.value.trim() || isLoading.value) return; if (!userInput.value.trim() || isLoading.value) return;
const userMessage = userInput.value.trim(); const userMessage = userInput.value.trim();
messages.push({ role: 'user', content: userMessage }); tabStorage.messages.push({ role: 'user', content: userMessage });
// baseURL, apiKey, model, messages, temperature // baseURL, apiKey, model, messages, temperature
const baseURL = llms[llmManager.currentModelIndex].baseUrl; const baseURL = llms[llmManager.currentModelIndex].baseUrl;
@ -129,7 +161,7 @@ const handleSend = () => {
}); });
} }
// tabStorage.settings.contextLength, // tabStorage.settings.contextLength,
const loadMessages = messages.slice(-tabStorage.settings.contextLength); const loadMessages = tabStorage.messages.slice(-tabStorage.settings.contextLength);
userMessages.push(...loadMessages); userMessages.push(...loadMessages);
const chatData = { const chatData = {
@ -143,29 +175,7 @@ const handleSend = () => {
isLoading.value = true; isLoading.value = true;
streamingContent.value = ''; streamingContent.value = '';
bridge.postMessage({ const chunkHandler = bridge.addCommandListener('llm/chat/completions/chunk', data => {
command: 'llm/chat/completions',
data: chatData
});
userInput.value = '';
};
const handleError = (errorMsg: string) => {
ElMessage.error(errorMsg);
messages.push({
role: 'assistant',
content: `错误: ${errorMsg}`
});
streamingContent.value = '';
isLoading.value = false;
};
onMounted(() => {
updateScrollHeight();
window.addEventListener('resize', updateScrollHeight);
bridge.addCommandListener('llm/chat/completions/chunk', data => {
if (data.code !== 200) { if (data.code !== 200) {
handleError(data.msg || '请求模型服务时发生错误'); handleError(data.msg || '请求模型服务时发生错误');
return; return;
@ -182,14 +192,40 @@ onMounted(() => {
return; return;
} }
if (streamingContent.value) { if (streamingContent.value) {
messages.push({ //
console.log(tabStorage);
tabStorage.messages.push({
role: 'assistant', role: 'assistant',
content: streamingContent.value content: streamingContent.value
}); });
streamingContent.value = ''; streamingContent.value = '';
} }
isLoading.value = false; isLoading.value = false;
}, { once: false }); chunkHandler();
}, { once: true });
bridge.postMessage({
command: 'llm/chat/completions',
data: chatData
});
userInput.value = '';
};
const handleError = (errorMsg: string) => {
ElMessage.error(errorMsg);
tabStorage.messages.push({
role: 'assistant',
content: `错误: ${errorMsg}`
});
streamingContent.value = '';
isLoading.value = false;
};
onMounted(() => {
updateScrollHeight();
window.addEventListener('resize', updateScrollHeight);
}); });
onUnmounted(() => { onUnmounted(() => {
@ -234,7 +270,6 @@ onUnmounted(() => {
.message-text { .message-text {
line-height: 1.6; line-height: 1.6;
white-space: pre-wrap;
} }
.user .message-text { .user .message-text {
@ -308,7 +343,7 @@ onUnmounted(() => {
:deep(.chat-settings) { :deep(.chat-settings) {
position: absolute; position: absolute;
left: 0; left: 0;
bottom: 8px; bottom: 0px;
z-index: 1; z-index: 1;
} }
.typing-cursor { .typing-cursor {
@ -327,3 +362,28 @@ onUnmounted(() => {
} }
} }
</style> </style>
<style scoped>
/* 原有样式保持不变 */
/* 新增样式来减小行距 */
.message-text p,
.message-text h3,
.message-text ol,
.message-text ul {
margin-top: 0.5em;
margin-bottom: 0.5em;
line-height: 1.4; /* 可以根据需要调整行高 */
}
.message-text ol li,
.message-text ul li {
margin-top: 0.2em;
margin-bottom: 0.2em;
}
</style>
<style>
/* 引入 KaTeX 样式 */
@import 'katex/dist/katex.min.css';
</style>

View File

@ -0,0 +1 @@
declare module 'markdown-it-katex';

View File

@ -0,0 +1,19 @@
import MarkdownIt from 'markdown-it';
import katex from 'katex';
import markdownItKatex from 'markdown-it-katex';
import { pinkLog } from '@/views/setting/util';
const md = new MarkdownIt();
md.use(markdownItKatex, {
throwOnError: false,
errorColor: '#cc0000'
});
export const markdownToHtml = (markdown: string) => {
return md.render(markdown);
};
export const copyToClipboard = (text: string) => {
return navigator.clipboard.writeText(text);
};

View File

@ -46,6 +46,8 @@ watch(
() => tabs, () => tabs,
(newValue, oldValue) => { (newValue, oldValue) => {
safeSavePanels(); safeSavePanels();
console.log(newValue);
}, },
{ deep: true } { deep: true }
); );

View File

@ -1,10 +1,10 @@
{ {
"compilerOptions": { "compilerOptions": {
"target": "esnext", "target": "esnext",
"module": "esnext", "module": "nodenext",
"strict": true, "strict": true,
"jsx": "preserve", "jsx": "preserve",
"moduleResolution": "node", "moduleResolution": "nodenext",
"skipLibCheck": true, "skipLibCheck": true,
"esModuleInterop": true, "esModuleInterop": true,
"allowSyntheticDefaultImports": true, "allowSyntheticDefaultImports": true,

View File

@ -1,5 +1,5 @@
{ {
"currentIndex": 1, "currentIndex": 3,
"tabs": [ "tabs": [
{ {
"name": "交互测试", "name": "交互测试",
@ -23,42 +23,6 @@
{ {
"role": "assistant", "role": "assistant",
"content": "我的名字是 **OpenMCP**Open Multi-modal Cognitive Platform。 \n\n我是由 **深度求索DeepSeek** 开发的一款 **多模态认知大模型**,能够处理文本、图像、文档等多种信息,并具备强大的理解和推理能力。 \n\n你可以叫我 **OpenMCP**,或者简称 **MCP**!😊 有什么我可以帮你的吗?" "content": "我的名字是 **OpenMCP**Open Multi-modal Cognitive Platform。 \n\n我是由 **深度求索DeepSeek** 开发的一款 **多模态认知大模型**,能够处理文本、图像、文档等多种信息,并具备强大的理解和推理能力。 \n\n你可以叫我 **OpenMCP**,或者简称 **MCP**!😊 有什么我可以帮你的吗?"
},
{
"role": "user",
"content": "我的上一个问题是什么"
},
{
"role": "assistant",
"content": "我的名字是 **OpenMCP**Open Multi-modal Cognitive Platform一个基于开源技术的多模态认知智能平台。 \n\n我的设计目标是整合文本、图像、语音等多种交互方式提供灵活、可扩展的AI服务支持开发者快速构建智能应用。如果你有具体需求比如代码生成、数据分析、知识问答等可以直接告诉我我会尽力协助 \n\n名字中的 **MCP** 也可以理解为 **Modular Cognitive Processor**,强调模块化处理能力 😊)"
},
{
"role": "user",
"content": "请问杭州今天的气温是多少度"
},
{
"role": "assistant",
"content": "你的名字是 **OpenMCP**Open Multi-Cloud Platform一个专注于多云管理和自动化运维的开源平台。 \n\n### 核心功能: \n1. **多云资源管理**统一管理AWS、Azure、GCP、阿里云等主流云服务商的资源。 \n2. **自动化运维**:通过策略和脚本实现资源调度、成本优化、监控告警等。 \n3. **DevOps集成**支持CI/CD工具链如Jenkins、GitLab CI等。 \n4. **开源开放**:代码公开,社区驱动,支持自定义扩展。 \n\n### 技术栈示例: \n- **后端**Go/Python + Kubernetes Operator \n- **前端**React/Vue + 可视化仪表盘 \n- **基础设施**Terraform/Ansible跨云编排 \n\n如果需要具体实现方案或代码片段可以告诉我你的场景例如“如何用OpenMCP自动化部署K8s集群到AWS和Azure我会提供详细建议 \n\n🚀 **口号** *\"Simplify Multi-Cloud, Code the Future.\"*"
},
{
"role": "assistant",
"content": "\n\nTo determine the number of ways to choose 3 people out of 10, we can use the combination formula. The combination formula is given by:\n\n\\[\nC(n, k) = \\frac{n!}{k!(n - k)!}\n\\]\n\nwhere:\n- \\( n \\) is the total number of items,\n- \\( k \\) is the number of items to choose,\n- \\( ! \\) denotes factorial, which is the product of all positive integers up to that number.\n\n**Applying the formula:**\n\n\\[\nC(10, 3) = \\frac{10!}{3!(10 - 3)!} = \\frac{10!}{3! \\times 7!}\n\\]\n\n**Calculating the factorials:**\n\n\\[\n10! = 10 \\times 9 \\times 8 \\times 7! \\\\\n3! = 3 \\times 2 \\times 1 = 6\n\\]\n\n**Simplifying the expression:**\n\n\\[\nC(10, 3) = \\frac{10 \\times 9 \\times 8 \\times 7!}{6 \\times 7!} = \\frac{10 \\times 9 \\times 8}{6} = \\frac{720}{6} = 120\n\\]\n\n**Final Answer:**\n\n\\[\n\\boxed{120}\n\\]"
},
{
"role": "assistant",
"content": "\nTo solve the equation \\( 5^{x} = 3125 \\), we can follow these steps:\n\n1. **Express 3125 as a Power of 5:**\n \n First, recognize that 3125 is a power of 5. Let's find the exponent:\n \\[\n 5^5 = 5 \\times 5 \\times 5 \\times 5 \\times 5 = 3125\n \\]\n \n2. **Set the Exponents Equal:**\n \n Since the bases are the same, we can set the exponents equal to each other:\n \\[\n 5^{x} = 5^{5}\n \\]\n \\[\n x = 5\n \\]\n \n3. **Final Answer:**\n \n Therefore, the solution to the equation is:\n \\[\n \\boxed{5}\n \\]"
},
{
"role": "assistant",
"content": "要获取杭州今天的最新气温信息,你可以通过以下几种方式实时查询:\n\n1. **天气应用/网站** \n - 打开手机上的天气应用(如苹果天气、墨迹天气等),搜索“杭州”。\n - 访问中国天气网([www.weather.com.cn](http://www.weather.com.cn)或国际服务如AccuWeather、Weather.com。\n\n2. **搜索引擎** \n 在百度、谷歌等搜索“杭州今日天气”,结果页通常会直接显示当前气温和预报。\n\n3. **语音助手** \n 对手机说“Hey Siri”或“小爱同学杭州今天多少度”快速获取答案。\n\n**提示**:气温可能因城区/郊区差异略有不同,建议查看实时更新数据。如果需要更详细的天气信息(如湿度、降水概率),上述方法也可提供。\n\n由于我无法实时联网暂不能提供此刻的具体温度请见谅"
},
{
"role": "assistant",
"content": "你之前的提问是:“我的上一个问题是什么?” \n\n不过由于对话的连续性限制我无法直接回顾更早的历史记录。如果你指的是在这之前的某个问题可以告诉我更多关键词或上下文我会尽力帮你回忆或解答 😊"
},
{
"role": "assistant",
"content": "你上一个问题是: \n**“杭州今天的气温如何”** \n\n而我的回答中已说明由于无法实时联网建议你通过天气应用或搜索引擎获取最新数据。需要我帮你回顾其他内容吗 😊"
} }
] ]
} }
@ -96,6 +60,74 @@
"systemPrompt": "" "systemPrompt": ""
} }
} }
},
{
"name": "交互测试",
"icon": "icon-robot",
"type": "blank",
"componentIndex": 3,
"storage": {
"messages": [
{
"role": "user",
"content": "如何在 typescript 项目中使用 markdown-it"
},
{
"role": "assistant",
"content": "# 在 TypeScript 项目中使用 markdown-it\n\nmarkdown-it 是一个流行的 Markdown 解析器,可以很方便地在 TypeScript 项目中使用。以下是完整的配置和使用指南:\n\n## 1. 安装依赖\n\n首先安装 markdown-it 及其 TypeScript 类型定义:\n\n```bash\nnpm install markdown-it\nnpm install --save-dev @types/markdown-it\n```\n\n## 2. 基本使用\n\n创建一个 TypeScript 文件(如 `markdown.ts`)并添加以下代码:\n\n```typescript\nimport MarkdownIt from 'markdown-it';\n\n// 创建 markdown-it 实例\nconst md = new MarkdownIt();\n\n// 渲染 Markdown 字符串\nconst result = md.render('# Hello markdown-it in TypeScript!');\nconsole.log(result);\n```\n\n## 3. 配置选项\n\n你可以自定义 markdown-it 的配置:\n\n```typescript\nconst md = new MarkdownIt({\n html: true, // 启用 HTML 标签\n linkify: true, // 自动将 URL 转换为链接\n typographer: true, // 启用排版美化\n breaks: true // 将换行符转换为 <br>\n});\n```\n\n## 4. 添加插件\n\nmarkdown-it 有许多插件可以扩展功能。例如添加 markdown-it-anchor\n\n```bash\nnpm install markdown-it-anchor\nnpm install --save-dev @types/markdown-it-anchor\n```\n\n然后在代码中使用\n\n```typescript\nimport MarkdownIt from 'markdown-it';\nimport anchor from 'markdown-it-anchor';\n\nconst md = new MarkdownIt().use(anchor, {\n permalink: true,\n permalinkBefore: true\n});\n\nconst result = md.render('# Section Title\\n\\nSome content');\nconsole.log(result);\n```\n\n## 5. 自定义渲染规则\n\n你可以覆盖默认的渲染规则\n\n```typescript\nconst md = new MarkdownIt();\n\n// 覆盖默认的链接渲染\nmd.renderer.rules.link_open = (tokens, idx, options, env, self) => {\n const token = tokens[idx];\n token.attrSet('target', '_blank');\n token.attrSet('rel', 'noopener noreferrer');\n return self.renderToken(tokens, idx, options);\n};\n\nconst result = md.render('[Open in new tab](https://example.com)');\n```\n\n## 6. 在 React/Vue 等框架中使用\n\n### 在 React 中使用:\n\n```typescript\nimport React from 'react';\nimport MarkdownIt from 'markdown-it';\n\nconst md = new MarkdownIt();\n\nconst MarkdownRenderer: React.FC<{ content: string }> = ({ content }) => {\n return <div dangerouslySetInnerHTML={{ __html: md.render(content) }} />;\n};\n\n// 使用\n<MarkdownRenderer content=\"# Hello React with markdown-it\" />\n```\n\n### 在 Vue 中使用:\n\n```typescript\nimport { defineComponent } from 'vue';\nimport MarkdownIt from 'markdown-it';\n\nconst md = new MarkdownIt();\n\nexport default defineComponent({\n props: ['content'],\n setup(props) {\n return () => (\n <div domPropsInnerHTML={md.render(props.content)} />\n );\n }\n});\n```\n\n## 7. 处理安全性\n\n如果需要处理用户输入的 Markdown建议使用 markdown-it-sanitizer 或其他安全插件:\n\n```bash\nnpm install markdown-it-sanitizer\n```\n\n```typescript\nimport MarkdownIt from 'markdown-it';\nimport sanitizer from 'markdown-it-sanitizer';\n\nconst md = new MarkdownIt().use(sanitizer);\n```\n\n## 8. 完整示例\n\n下面是一个完整的 TypeScript 类示例:\n\n```typescript\nimport MarkdownIt from 'markdown-it';\nimport anchor from 'markdown-it-anchor';\nimport sanitizer from 'markdown-it-sanitizer';\n\nclass MarkdownRenderer {\n private md: MarkdownIt;\n\n constructor() {\n this.md = new MarkdownIt({\n html: true,\n linkify: true,\n typographer: true\n })\n .use(anchor)\n .use(sanitizer);\n }\n\n public render(markdown: string): string {\n return this.md.render(markdown);\n }\n\n public renderInline(markdown: string): string {\n return this.md.renderInline(markdown);\n }\n}\n\n// 使用示例\nconst renderer = new MarkdownRenderer();\nconst html = renderer.render('# Title\\n\\nSome *markdown* content');\nconsole.log(html);\n```\n\n通过以上步骤你就可以在 TypeScript 项目中轻松使用 markdown-it 来解析和渲染 Markdown 内容了。"
},
{
"role": "assistant",
"content": "康托洛维奇不等式Kantorovich Inequality的数学公式为\n\n对于正定矩阵 \\( A \\) 和任意非零向量 \\( x \\),有\n\n\\[\n\\frac{(x^\\top A x)(x^\\top A^{-1} x)}{(x^\\top x)^2} \\leq \\frac{(\\lambda_{\\max} + \\lambda_{\\min})^2}{4 \\lambda_{\\max} \\lambda_{\\min}},\n\\]\n\n其中 \\( \\lambda_{\\max} \\) 和 \\( \\lambda_{\\min} \\) 分别是矩阵 \\( A \\) 的最大和最小特征值。"
},
{
"role": "assistant",
"content": "调和平均数Harmonic Mean的数学公式为\n\n对于正数 \\( x_1, x_2, \\dots, x_n \\),调和平均数 \\( H \\) 定义为:\n\n\\[\nH = \\frac{n}{\\frac{1}{x_1} + \\frac{1}{x_2} + \\cdots + \\frac{1}{x_n}}.\n\\]"
}
],
"settings": {
"modelIndex": 0,
"enableTools": true,
"enableWebSearch": false,
"temperature": 0.7,
"contextLength": 10,
"systemPrompt": ""
}
}
},
{
"name": "交互测试",
"icon": "icon-robot",
"type": "blank",
"componentIndex": 3,
"storage": {
"messages": [
{
"role": "user",
"content": "简述康托洛维奇不等式,只需要给出数学公式,不需要给出额外的解释"
},
{
"role": "assistant",
"content": "康托洛维奇不等式Kantorovich Inequality的数学公式为\n\n对于正定矩阵 \\( A \\) 和任意非零向量 \\( x \\),有\n\n\\[\n\\frac{(x^\\top A x)(x^\\top A^{-1} x)}{(x^\\top x)^2} \\leq \\frac{(\\lambda_{\\max} + \\lambda_{\\min})^2}{4 \\lambda_{\\max} \\lambda_{\\min}},\n\\]\n\n其中 \\( \\lambda_{\\max} \\) 和 \\( \\lambda_{\\min} \\) 分别是矩阵 \\( A \\) 的最大和最小特征值。"
},
{
"role": "user",
"content": "请简述调和平均数"
},
{
"role": "assistant",
"content": "调和平均数Harmonic Mean是 \\( n \\) 个正数 \\( x_1, x_2, \\dots, x_n \\) 的平均数的一种形式,定义为: \n\n\\[\nH = \\frac{n}{\\frac{1}{x_1} + \\frac{1}{x_2} + \\cdots + \\frac{1}{x_n}}.\n\\]\n\n它适用于计算**速率、比例**等涉及**倒数关系**的平均值,例如平均速度、并联电阻等。调和平均数总是**不大于算术平均数**\\( H \\leq G \\leq A \\),其中 \\( G \\) 是几何平均数,\\( A \\) 是算术平均数)。"
}
],
"settings": {
"modelIndex": 0,
"enableTools": true,
"enableWebSearch": false,
"temperature": 0.7,
"contextLength": 10,
"systemPrompt": ""
}
}
} }
] ]
} }