feat: API access key management #2846 (#2865)

### What problem does this PR solve?

feat: API access key management #2846
feat: Render markdown file with remark-loader #2846

### Type of change

- [ ] Bug Fix (non-breaking change which fixes an issue)
- [x] New Feature (non-breaking change which adds functionality)
- [ ] Documentation Update
- [ ] Refactoring
- [ ] Performance Improvement
- [ ] Other (please describe):
This commit is contained in:
balibabu 2024-10-16 15:57:39 +08:00 committed by GitHub
parent 4991107822
commit e5d3ab0332
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
32 changed files with 1303 additions and 165 deletions

View File

@ -25,6 +25,9 @@ export default defineConfig({
hack: `true; @import "~@/less/index.less";`,
},
},
mdx: {
loader: 'remark-loader',
},
devtool: 'source-map',
copy: ['src/conf.json'],
proxy: {
@ -36,4 +39,16 @@ export default defineConfig({
// pathRewrite: { '^/v1': '/v1' },
},
},
chainWebpack(memo, args) {
memo.module
.rule('markdown')
.test(/\.md$/)
.use('html-loader')
.loader('html-loader')
.end()
.use('remark-loader')
.loader('remark-loader');
return memo;
},
});

882
web/package-lock.json generated
View File

@ -67,6 +67,7 @@
"@umijs/lint": "^4.1.1",
"@umijs/plugins": "^4.1.0",
"cross-env": "^7.0.3",
"html-loader": "^5.1.0",
"husky": "^9.0.11",
"jest": "^29.7.0",
"jest-environment-jsdom": "^29.7.0",
@ -75,6 +76,7 @@
"prettier-plugin-organize-imports": "^3.2.4",
"prettier-plugin-packagejson": "^2.4.9",
"react-dev-inspector": "^2.0.1",
"remark-loader": "^6.0.0",
"ts-node": "^10.9.2",
"typescript": "^5.0.3",
"umi-plugin-icons": "^0.1.1"
@ -13411,6 +13413,15 @@
}
]
},
"node_modules/front-matter": {
"version": "4.0.2",
"resolved": "https://registry.npmmirror.com/front-matter/-/front-matter-4.0.2.tgz",
"integrity": "sha512-I8ZuJ/qG92NWX8i5x1Y8qyj3vizhXS31OxjKDu3LKP+7/qBgfIKValiZIEwoVoJKUHlhWtYrktkxV1XsX+pPlg==",
"dev": true,
"dependencies": {
"js-yaml": "^3.13.1"
}
},
"node_modules/fs-extra": {
"version": "10.1.0",
"resolved": "https://registry.npmmirror.com/fs-extra/-/fs-extra-10.1.0.tgz",
@ -14279,6 +14290,56 @@
"integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==",
"devOptional": true
},
"node_modules/html-loader": {
"version": "5.1.0",
"resolved": "https://registry.npmmirror.com/html-loader/-/html-loader-5.1.0.tgz",
"integrity": "sha512-Jb3xwDbsm0W3qlXrCZwcYqYGnYz55hb6aoKQTlzyZPXsPpi6tHXzAfqalecglMQgNvtEfxrCQPaKT90Irt5XDA==",
"dev": true,
"dependencies": {
"html-minifier-terser": "^7.2.0",
"parse5": "^7.1.2"
},
"engines": {
"node": ">= 18.12.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/webpack"
},
"peerDependencies": {
"webpack": "^5.0.0"
}
},
"node_modules/html-loader/node_modules/commander": {
"version": "10.0.1",
"resolved": "https://registry.npmmirror.com/commander/-/commander-10.0.1.tgz",
"integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==",
"dev": true,
"engines": {
"node": ">=14"
}
},
"node_modules/html-loader/node_modules/html-minifier-terser": {
"version": "7.2.0",
"resolved": "https://registry.npmmirror.com/html-minifier-terser/-/html-minifier-terser-7.2.0.tgz",
"integrity": "sha512-tXgn3QfqPIpGl9o+K5tpcj3/MN4SfLtsx2GWwBC3SSd0tXQGyF3gsSqad8loJgKZGM3ZxbYDd5yhiBIdWpmvLA==",
"dev": true,
"dependencies": {
"camel-case": "^4.1.2",
"clean-css": "~5.3.2",
"commander": "^10.0.0",
"entities": "^4.4.0",
"param-case": "^3.0.4",
"relateurl": "^0.2.7",
"terser": "^5.15.1"
},
"bin": {
"html-minifier-terser": "cli.js"
},
"engines": {
"node": "^14.13.1 || >=16.0.0"
}
},
"node_modules/html-minifier-terser": {
"version": "6.1.0",
"resolved": "https://registry.npmmirror.com/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz",
@ -19895,6 +19956,16 @@
"node": "*"
}
},
"node_modules/mri": {
"version": "1.2.0",
"resolved": "https://registry.npmmirror.com/mri/-/mri-1.2.0.tgz",
"integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==",
"dev": true,
"peer": true,
"engines": {
"node": ">=4"
}
},
"node_modules/ms": {
"version": "2.1.2",
"resolved": "https://registry.npmmirror.com/ms/-/ms-2.1.2.tgz",
@ -23889,6 +23960,23 @@
"node": ">= 0.10"
}
},
"node_modules/remark": {
"version": "14.0.3",
"resolved": "https://registry.npmmirror.com/remark/-/remark-14.0.3.tgz",
"integrity": "sha512-bfmJW1dmR2LvaMJuAnE88pZP9DktIFYXazkTfOIKZzi3Knk9lT0roItIA24ydOucI3bV/g/tXBA6hzqq3FV9Ew==",
"dev": true,
"peer": true,
"dependencies": {
"@types/mdast": "^3.0.0",
"remark-parse": "^10.0.0",
"remark-stringify": "^10.0.0",
"unified": "^10.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/unified"
}
},
"node_modules/remark-gfm": {
"version": "4.0.0",
"resolved": "https://registry.npmmirror.com/remark-gfm/-/remark-gfm-4.0.0.tgz",
@ -23902,6 +23990,26 @@
"unified": "^11.0.0"
}
},
"node_modules/remark-loader": {
"version": "6.0.0",
"resolved": "https://registry.npmmirror.com/remark-loader/-/remark-loader-6.0.0.tgz",
"integrity": "sha512-3Z4WLyVYbI1F6TQNnA9/iuHsoRcu8ruH2ABixLpgSWiSiYdNgURgLdpbdze8jTm2+VWWcAq9xIH7maWSpi2sSw==",
"dev": true,
"dependencies": {
"front-matter": "^4.0.2"
},
"engines": {
"node": ">= 18.12.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/webpack"
},
"peerDependencies": {
"remark": "^14.0.0",
"webpack": "^5.0.0"
}
},
"node_modules/remark-parse": {
"version": "11.0.0",
"resolved": "https://registry.npmmirror.com/remark-parse/-/remark-parse-11.0.0.tgz",
@ -23935,6 +24043,728 @@
"unified": "^11.0.0"
}
},
"node_modules/remark/node_modules/@types/mdast": {
"version": "3.0.15",
"resolved": "https://registry.npmmirror.com/@types/mdast/-/mdast-3.0.15.tgz",
"integrity": "sha512-LnwD+mUEfxWMa1QpDraczIn6k0Ee3SMicuYSSzS6ZYl2gKS09EClnJYGd8Du6rfc5r/GZEk5o1mRb8TaTj03sQ==",
"dev": true,
"peer": true,
"dependencies": {
"@types/unist": "^2"
}
},
"node_modules/remark/node_modules/@types/unist": {
"version": "2.0.11",
"resolved": "https://registry.npmmirror.com/@types/unist/-/unist-2.0.11.tgz",
"integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==",
"dev": true,
"peer": true
},
"node_modules/remark/node_modules/is-buffer": {
"version": "2.0.5",
"resolved": "https://registry.npmmirror.com/is-buffer/-/is-buffer-2.0.5.tgz",
"integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==",
"dev": true,
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
],
"peer": true,
"engines": {
"node": ">=4"
}
},
"node_modules/remark/node_modules/mdast-util-from-markdown": {
"version": "1.3.1",
"resolved": "https://registry.npmmirror.com/mdast-util-from-markdown/-/mdast-util-from-markdown-1.3.1.tgz",
"integrity": "sha512-4xTO/M8c82qBcnQc1tgpNtubGUW/Y1tBQ1B0i5CtSoelOLKFYlElIr3bvgREYYO5iRqbMY1YuqZng0GVOI8Qww==",
"dev": true,
"peer": true,
"dependencies": {
"@types/mdast": "^3.0.0",
"@types/unist": "^2.0.0",
"decode-named-character-reference": "^1.0.0",
"mdast-util-to-string": "^3.1.0",
"micromark": "^3.0.0",
"micromark-util-decode-numeric-character-reference": "^1.0.0",
"micromark-util-decode-string": "^1.0.0",
"micromark-util-normalize-identifier": "^1.0.0",
"micromark-util-symbol": "^1.0.0",
"micromark-util-types": "^1.0.0",
"unist-util-stringify-position": "^3.0.0",
"uvu": "^0.5.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/unified"
}
},
"node_modules/remark/node_modules/mdast-util-phrasing": {
"version": "3.0.1",
"resolved": "https://registry.npmmirror.com/mdast-util-phrasing/-/mdast-util-phrasing-3.0.1.tgz",
"integrity": "sha512-WmI1gTXUBJo4/ZmSk79Wcb2HcjPJBzM1nlI/OUWA8yk2X9ik3ffNbBGsU+09BFmXaL1IBb9fiuvq6/KMiNycSg==",
"dev": true,
"peer": true,
"dependencies": {
"@types/mdast": "^3.0.0",
"unist-util-is": "^5.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/unified"
}
},
"node_modules/remark/node_modules/mdast-util-to-markdown": {
"version": "1.5.0",
"resolved": "https://registry.npmmirror.com/mdast-util-to-markdown/-/mdast-util-to-markdown-1.5.0.tgz",
"integrity": "sha512-bbv7TPv/WC49thZPg3jXuqzuvI45IL2EVAr/KxF0BSdHsU0ceFHOmwQn6evxAh1GaoK/6GQ1wp4R4oW2+LFL/A==",
"dev": true,
"peer": true,
"dependencies": {
"@types/mdast": "^3.0.0",
"@types/unist": "^2.0.0",
"longest-streak": "^3.0.0",
"mdast-util-phrasing": "^3.0.0",
"mdast-util-to-string": "^3.0.0",
"micromark-util-decode-string": "^1.0.0",
"unist-util-visit": "^4.0.0",
"zwitch": "^2.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/unified"
}
},
"node_modules/remark/node_modules/mdast-util-to-string": {
"version": "3.2.0",
"resolved": "https://registry.npmmirror.com/mdast-util-to-string/-/mdast-util-to-string-3.2.0.tgz",
"integrity": "sha512-V4Zn/ncyN1QNSqSBxTrMOLpjr+IKdHl2v3KVLoWmDPscP4r9GcCi71gjgvUV1SFSKh92AjAG4peFuBl2/YgCJg==",
"dev": true,
"peer": true,
"dependencies": {
"@types/mdast": "^3.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/unified"
}
},
"node_modules/remark/node_modules/micromark": {
"version": "3.2.0",
"resolved": "https://registry.npmmirror.com/micromark/-/micromark-3.2.0.tgz",
"integrity": "sha512-uD66tJj54JLYq0De10AhWycZWGQNUvDI55xPgk2sQM5kn1JYlhbCMTtEeT27+vAhW2FBQxLlOmS3pmA7/2z4aA==",
"dev": true,
"funding": [
{
"type": "GitHub Sponsors",
"url": "https://github.com/sponsors/unifiedjs"
},
{
"type": "OpenCollective",
"url": "https://opencollective.com/unified"
}
],
"peer": true,
"dependencies": {
"@types/debug": "^4.0.0",
"debug": "^4.0.0",
"decode-named-character-reference": "^1.0.0",
"micromark-core-commonmark": "^1.0.1",
"micromark-factory-space": "^1.0.0",
"micromark-util-character": "^1.0.0",
"micromark-util-chunked": "^1.0.0",
"micromark-util-combine-extensions": "^1.0.0",
"micromark-util-decode-numeric-character-reference": "^1.0.0",
"micromark-util-encode": "^1.0.0",
"micromark-util-normalize-identifier": "^1.0.0",
"micromark-util-resolve-all": "^1.0.0",
"micromark-util-sanitize-uri": "^1.0.0",
"micromark-util-subtokenize": "^1.0.0",
"micromark-util-symbol": "^1.0.0",
"micromark-util-types": "^1.0.1",
"uvu": "^0.5.0"
}
},
"node_modules/remark/node_modules/micromark-core-commonmark": {
"version": "1.1.0",
"resolved": "https://registry.npmmirror.com/micromark-core-commonmark/-/micromark-core-commonmark-1.1.0.tgz",
"integrity": "sha512-BgHO1aRbolh2hcrzL2d1La37V0Aoz73ymF8rAcKnohLy93titmv62E0gP8Hrx9PKcKrqCZ1BbLGbP3bEhoXYlw==",
"dev": true,
"funding": [
{
"type": "GitHub Sponsors",
"url": "https://github.com/sponsors/unifiedjs"
},
{
"type": "OpenCollective",
"url": "https://opencollective.com/unified"
}
],
"peer": true,
"dependencies": {
"decode-named-character-reference": "^1.0.0",
"micromark-factory-destination": "^1.0.0",
"micromark-factory-label": "^1.0.0",
"micromark-factory-space": "^1.0.0",
"micromark-factory-title": "^1.0.0",
"micromark-factory-whitespace": "^1.0.0",
"micromark-util-character": "^1.0.0",
"micromark-util-chunked": "^1.0.0",
"micromark-util-classify-character": "^1.0.0",
"micromark-util-html-tag-name": "^1.0.0",
"micromark-util-normalize-identifier": "^1.0.0",
"micromark-util-resolve-all": "^1.0.0",
"micromark-util-subtokenize": "^1.0.0",
"micromark-util-symbol": "^1.0.0",
"micromark-util-types": "^1.0.1",
"uvu": "^0.5.0"
}
},
"node_modules/remark/node_modules/micromark-factory-destination": {
"version": "1.1.0",
"resolved": "https://registry.npmmirror.com/micromark-factory-destination/-/micromark-factory-destination-1.1.0.tgz",
"integrity": "sha512-XaNDROBgx9SgSChd69pjiGKbV+nfHGDPVYFs5dOoDd7ZnMAE+Cuu91BCpsY8RT2NP9vo/B8pds2VQNCLiu0zhg==",
"dev": true,
"funding": [
{
"type": "GitHub Sponsors",
"url": "https://github.com/sponsors/unifiedjs"
},
{
"type": "OpenCollective",
"url": "https://opencollective.com/unified"
}
],
"peer": true,
"dependencies": {
"micromark-util-character": "^1.0.0",
"micromark-util-symbol": "^1.0.0",
"micromark-util-types": "^1.0.0"
}
},
"node_modules/remark/node_modules/micromark-factory-label": {
"version": "1.1.0",
"resolved": "https://registry.npmmirror.com/micromark-factory-label/-/micromark-factory-label-1.1.0.tgz",
"integrity": "sha512-OLtyez4vZo/1NjxGhcpDSbHQ+m0IIGnT8BoPamh+7jVlzLJBH98zzuCoUeMxvM6WsNeh8wx8cKvqLiPHEACn0w==",
"dev": true,
"funding": [
{
"type": "GitHub Sponsors",
"url": "https://github.com/sponsors/unifiedjs"
},
{
"type": "OpenCollective",
"url": "https://opencollective.com/unified"
}
],
"peer": true,
"dependencies": {
"micromark-util-character": "^1.0.0",
"micromark-util-symbol": "^1.0.0",
"micromark-util-types": "^1.0.0",
"uvu": "^0.5.0"
}
},
"node_modules/remark/node_modules/micromark-factory-space": {
"version": "1.1.0",
"resolved": "https://registry.npmmirror.com/micromark-factory-space/-/micromark-factory-space-1.1.0.tgz",
"integrity": "sha512-cRzEj7c0OL4Mw2v6nwzttyOZe8XY/Z8G0rzmWQZTBi/jjwyw/U4uqKtUORXQrR5bAZZnbTI/feRV/R7hc4jQYQ==",
"dev": true,
"funding": [
{
"type": "GitHub Sponsors",
"url": "https://github.com/sponsors/unifiedjs"
},
{
"type": "OpenCollective",
"url": "https://opencollective.com/unified"
}
],
"peer": true,
"dependencies": {
"micromark-util-character": "^1.0.0",
"micromark-util-types": "^1.0.0"
}
},
"node_modules/remark/node_modules/micromark-factory-title": {
"version": "1.1.0",
"resolved": "https://registry.npmmirror.com/micromark-factory-title/-/micromark-factory-title-1.1.0.tgz",
"integrity": "sha512-J7n9R3vMmgjDOCY8NPw55jiyaQnH5kBdV2/UXCtZIpnHH3P6nHUKaH7XXEYuWwx/xUJcawa8plLBEjMPU24HzQ==",
"dev": true,
"funding": [
{
"type": "GitHub Sponsors",
"url": "https://github.com/sponsors/unifiedjs"
},
{
"type": "OpenCollective",
"url": "https://opencollective.com/unified"
}
],
"peer": true,
"dependencies": {
"micromark-factory-space": "^1.0.0",
"micromark-util-character": "^1.0.0",
"micromark-util-symbol": "^1.0.0",
"micromark-util-types": "^1.0.0"
}
},
"node_modules/remark/node_modules/micromark-factory-whitespace": {
"version": "1.1.0",
"resolved": "https://registry.npmmirror.com/micromark-factory-whitespace/-/micromark-factory-whitespace-1.1.0.tgz",
"integrity": "sha512-v2WlmiymVSp5oMg+1Q0N1Lxmt6pMhIHD457whWM7/GUlEks1hI9xj5w3zbc4uuMKXGisksZk8DzP2UyGbGqNsQ==",
"dev": true,
"funding": [
{
"type": "GitHub Sponsors",
"url": "https://github.com/sponsors/unifiedjs"
},
{
"type": "OpenCollective",
"url": "https://opencollective.com/unified"
}
],
"peer": true,
"dependencies": {
"micromark-factory-space": "^1.0.0",
"micromark-util-character": "^1.0.0",
"micromark-util-symbol": "^1.0.0",
"micromark-util-types": "^1.0.0"
}
},
"node_modules/remark/node_modules/micromark-util-character": {
"version": "1.2.0",
"resolved": "https://registry.npmmirror.com/micromark-util-character/-/micromark-util-character-1.2.0.tgz",
"integrity": "sha512-lXraTwcX3yH/vMDaFWCQJP1uIszLVebzUa3ZHdrgxr7KEU/9mL4mVgCpGbyhvNLNlauROiNUq7WN5u7ndbY6xg==",
"dev": true,
"funding": [
{
"type": "GitHub Sponsors",
"url": "https://github.com/sponsors/unifiedjs"
},
{
"type": "OpenCollective",
"url": "https://opencollective.com/unified"
}
],
"peer": true,
"dependencies": {
"micromark-util-symbol": "^1.0.0",
"micromark-util-types": "^1.0.0"
}
},
"node_modules/remark/node_modules/micromark-util-chunked": {
"version": "1.1.0",
"resolved": "https://registry.npmmirror.com/micromark-util-chunked/-/micromark-util-chunked-1.1.0.tgz",
"integrity": "sha512-Ye01HXpkZPNcV6FiyoW2fGZDUw4Yc7vT0E9Sad83+bEDiCJ1uXu0S3mr8WLpsz3HaG3x2q0HM6CTuPdcZcluFQ==",
"dev": true,
"funding": [
{
"type": "GitHub Sponsors",
"url": "https://github.com/sponsors/unifiedjs"
},
{
"type": "OpenCollective",
"url": "https://opencollective.com/unified"
}
],
"peer": true,
"dependencies": {
"micromark-util-symbol": "^1.0.0"
}
},
"node_modules/remark/node_modules/micromark-util-classify-character": {
"version": "1.1.0",
"resolved": "https://registry.npmmirror.com/micromark-util-classify-character/-/micromark-util-classify-character-1.1.0.tgz",
"integrity": "sha512-SL0wLxtKSnklKSUplok1WQFoGhUdWYKggKUiqhX+Swala+BtptGCu5iPRc+xvzJ4PXE/hwM3FNXsfEVgoZsWbw==",
"dev": true,
"funding": [
{
"type": "GitHub Sponsors",
"url": "https://github.com/sponsors/unifiedjs"
},
{
"type": "OpenCollective",
"url": "https://opencollective.com/unified"
}
],
"peer": true,
"dependencies": {
"micromark-util-character": "^1.0.0",
"micromark-util-symbol": "^1.0.0",
"micromark-util-types": "^1.0.0"
}
},
"node_modules/remark/node_modules/micromark-util-combine-extensions": {
"version": "1.1.0",
"resolved": "https://registry.npmmirror.com/micromark-util-combine-extensions/-/micromark-util-combine-extensions-1.1.0.tgz",
"integrity": "sha512-Q20sp4mfNf9yEqDL50WwuWZHUrCO4fEyeDCnMGmG5Pr0Cz15Uo7KBs6jq+dq0EgX4DPwwrh9m0X+zPV1ypFvUA==",
"dev": true,
"funding": [
{
"type": "GitHub Sponsors",
"url": "https://github.com/sponsors/unifiedjs"
},
{
"type": "OpenCollective",
"url": "https://opencollective.com/unified"
}
],
"peer": true,
"dependencies": {
"micromark-util-chunked": "^1.0.0",
"micromark-util-types": "^1.0.0"
}
},
"node_modules/remark/node_modules/micromark-util-decode-numeric-character-reference": {
"version": "1.1.0",
"resolved": "https://registry.npmmirror.com/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-1.1.0.tgz",
"integrity": "sha512-m9V0ExGv0jB1OT21mrWcuf4QhP46pH1KkfWy9ZEezqHKAxkj4mPCy3nIH1rkbdMlChLHX531eOrymlwyZIf2iw==",
"dev": true,
"funding": [
{
"type": "GitHub Sponsors",
"url": "https://github.com/sponsors/unifiedjs"
},
{
"type": "OpenCollective",
"url": "https://opencollective.com/unified"
}
],
"peer": true,
"dependencies": {
"micromark-util-symbol": "^1.0.0"
}
},
"node_modules/remark/node_modules/micromark-util-decode-string": {
"version": "1.1.0",
"resolved": "https://registry.npmmirror.com/micromark-util-decode-string/-/micromark-util-decode-string-1.1.0.tgz",
"integrity": "sha512-YphLGCK8gM1tG1bd54azwyrQRjCFcmgj2S2GoJDNnh4vYtnL38JS8M4gpxzOPNyHdNEpheyWXCTnnTDY3N+NVQ==",
"dev": true,
"funding": [
{
"type": "GitHub Sponsors",
"url": "https://github.com/sponsors/unifiedjs"
},
{
"type": "OpenCollective",
"url": "https://opencollective.com/unified"
}
],
"peer": true,
"dependencies": {
"decode-named-character-reference": "^1.0.0",
"micromark-util-character": "^1.0.0",
"micromark-util-decode-numeric-character-reference": "^1.0.0",
"micromark-util-symbol": "^1.0.0"
}
},
"node_modules/remark/node_modules/micromark-util-encode": {
"version": "1.1.0",
"resolved": "https://registry.npmmirror.com/micromark-util-encode/-/micromark-util-encode-1.1.0.tgz",
"integrity": "sha512-EuEzTWSTAj9PA5GOAs992GzNh2dGQO52UvAbtSOMvXTxv3Criqb6IOzJUBCmEqrrXSblJIJBbFFv6zPxpreiJw==",
"dev": true,
"funding": [
{
"type": "GitHub Sponsors",
"url": "https://github.com/sponsors/unifiedjs"
},
{
"type": "OpenCollective",
"url": "https://opencollective.com/unified"
}
],
"peer": true
},
"node_modules/remark/node_modules/micromark-util-html-tag-name": {
"version": "1.2.0",
"resolved": "https://registry.npmmirror.com/micromark-util-html-tag-name/-/micromark-util-html-tag-name-1.2.0.tgz",
"integrity": "sha512-VTQzcuQgFUD7yYztuQFKXT49KghjtETQ+Wv/zUjGSGBioZnkA4P1XXZPT1FHeJA6RwRXSF47yvJ1tsJdoxwO+Q==",
"dev": true,
"funding": [
{
"type": "GitHub Sponsors",
"url": "https://github.com/sponsors/unifiedjs"
},
{
"type": "OpenCollective",
"url": "https://opencollective.com/unified"
}
],
"peer": true
},
"node_modules/remark/node_modules/micromark-util-normalize-identifier": {
"version": "1.1.0",
"resolved": "https://registry.npmmirror.com/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-1.1.0.tgz",
"integrity": "sha512-N+w5vhqrBihhjdpM8+5Xsxy71QWqGn7HYNUvch71iV2PM7+E3uWGox1Qp90loa1ephtCxG2ftRV/Conitc6P2Q==",
"dev": true,
"funding": [
{
"type": "GitHub Sponsors",
"url": "https://github.com/sponsors/unifiedjs"
},
{
"type": "OpenCollective",
"url": "https://opencollective.com/unified"
}
],
"peer": true,
"dependencies": {
"micromark-util-symbol": "^1.0.0"
}
},
"node_modules/remark/node_modules/micromark-util-resolve-all": {
"version": "1.1.0",
"resolved": "https://registry.npmmirror.com/micromark-util-resolve-all/-/micromark-util-resolve-all-1.1.0.tgz",
"integrity": "sha512-b/G6BTMSg+bX+xVCshPTPyAu2tmA0E4X98NSR7eIbeC6ycCqCeE7wjfDIgzEbkzdEVJXRtOG4FbEm/uGbCRouA==",
"dev": true,
"funding": [
{
"type": "GitHub Sponsors",
"url": "https://github.com/sponsors/unifiedjs"
},
{
"type": "OpenCollective",
"url": "https://opencollective.com/unified"
}
],
"peer": true,
"dependencies": {
"micromark-util-types": "^1.0.0"
}
},
"node_modules/remark/node_modules/micromark-util-sanitize-uri": {
"version": "1.2.0",
"resolved": "https://registry.npmmirror.com/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-1.2.0.tgz",
"integrity": "sha512-QO4GXv0XZfWey4pYFndLUKEAktKkG5kZTdUNaTAkzbuJxn2tNBOr+QtxR2XpWaMhbImT2dPzyLrPXLlPhph34A==",
"dev": true,
"funding": [
{
"type": "GitHub Sponsors",
"url": "https://github.com/sponsors/unifiedjs"
},
{
"type": "OpenCollective",
"url": "https://opencollective.com/unified"
}
],
"peer": true,
"dependencies": {
"micromark-util-character": "^1.0.0",
"micromark-util-encode": "^1.0.0",
"micromark-util-symbol": "^1.0.0"
}
},
"node_modules/remark/node_modules/micromark-util-subtokenize": {
"version": "1.1.0",
"resolved": "https://registry.npmmirror.com/micromark-util-subtokenize/-/micromark-util-subtokenize-1.1.0.tgz",
"integrity": "sha512-kUQHyzRoxvZO2PuLzMt2P/dwVsTiivCK8icYTeR+3WgbuPqfHgPPy7nFKbeqRivBvn/3N3GBiNC+JRTMSxEC7A==",
"dev": true,
"funding": [
{
"type": "GitHub Sponsors",
"url": "https://github.com/sponsors/unifiedjs"
},
{
"type": "OpenCollective",
"url": "https://opencollective.com/unified"
}
],
"peer": true,
"dependencies": {
"micromark-util-chunked": "^1.0.0",
"micromark-util-symbol": "^1.0.0",
"micromark-util-types": "^1.0.0",
"uvu": "^0.5.0"
}
},
"node_modules/remark/node_modules/micromark-util-symbol": {
"version": "1.1.0",
"resolved": "https://registry.npmmirror.com/micromark-util-symbol/-/micromark-util-symbol-1.1.0.tgz",
"integrity": "sha512-uEjpEYY6KMs1g7QfJ2eX1SQEV+ZT4rUD3UcF6l57acZvLNK7PBZL+ty82Z1qhK1/yXIY4bdx04FKMgR0g4IAag==",
"dev": true,
"funding": [
{
"type": "GitHub Sponsors",
"url": "https://github.com/sponsors/unifiedjs"
},
{
"type": "OpenCollective",
"url": "https://opencollective.com/unified"
}
],
"peer": true
},
"node_modules/remark/node_modules/micromark-util-types": {
"version": "1.1.0",
"resolved": "https://registry.npmmirror.com/micromark-util-types/-/micromark-util-types-1.1.0.tgz",
"integrity": "sha512-ukRBgie8TIAcacscVHSiddHjO4k/q3pnedmzMQ4iwDcK0FtFCohKOlFbaOL/mPgfnPsL3C1ZyxJa4sbWrBl3jg==",
"dev": true,
"funding": [
{
"type": "GitHub Sponsors",
"url": "https://github.com/sponsors/unifiedjs"
},
{
"type": "OpenCollective",
"url": "https://opencollective.com/unified"
}
],
"peer": true
},
"node_modules/remark/node_modules/remark-parse": {
"version": "10.0.2",
"resolved": "https://registry.npmmirror.com/remark-parse/-/remark-parse-10.0.2.tgz",
"integrity": "sha512-3ydxgHa/ZQzG8LvC7jTXccARYDcRld3VfcgIIFs7bI6vbRSxJJmzgLEIIoYKyrfhaY+ujuWaf/PJiMZXoiCXgw==",
"dev": true,
"peer": true,
"dependencies": {
"@types/mdast": "^3.0.0",
"mdast-util-from-markdown": "^1.0.0",
"unified": "^10.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/unified"
}
},
"node_modules/remark/node_modules/remark-stringify": {
"version": "10.0.3",
"resolved": "https://registry.npmmirror.com/remark-stringify/-/remark-stringify-10.0.3.tgz",
"integrity": "sha512-koyOzCMYoUHudypbj4XpnAKFbkddRMYZHwghnxd7ue5210WzGw6kOBwauJTRUMq16jsovXx8dYNvSSWP89kZ3A==",
"dev": true,
"peer": true,
"dependencies": {
"@types/mdast": "^3.0.0",
"mdast-util-to-markdown": "^1.0.0",
"unified": "^10.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/unified"
}
},
"node_modules/remark/node_modules/unified": {
"version": "10.1.2",
"resolved": "https://registry.npmmirror.com/unified/-/unified-10.1.2.tgz",
"integrity": "sha512-pUSWAi/RAnVy1Pif2kAoeWNBa3JVrx0MId2LASj8G+7AiHWoKZNTomq6LG326T68U7/e263X6fTdcXIy7XnF7Q==",
"dev": true,
"peer": true,
"dependencies": {
"@types/unist": "^2.0.0",
"bail": "^2.0.0",
"extend": "^3.0.0",
"is-buffer": "^2.0.0",
"is-plain-obj": "^4.0.0",
"trough": "^2.0.0",
"vfile": "^5.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/unified"
}
},
"node_modules/remark/node_modules/unist-util-is": {
"version": "5.2.1",
"resolved": "https://registry.npmmirror.com/unist-util-is/-/unist-util-is-5.2.1.tgz",
"integrity": "sha512-u9njyyfEh43npf1M+yGKDGVPbY/JWEemg5nH05ncKPfi+kBbKBJoTdsogMu33uhytuLlv9y0O7GH7fEdwLdLQw==",
"dev": true,
"peer": true,
"dependencies": {
"@types/unist": "^2.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/unified"
}
},
"node_modules/remark/node_modules/unist-util-stringify-position": {
"version": "3.0.3",
"resolved": "https://registry.npmmirror.com/unist-util-stringify-position/-/unist-util-stringify-position-3.0.3.tgz",
"integrity": "sha512-k5GzIBZ/QatR8N5X2y+drfpWG8IDBzdnVj6OInRNWm1oXrzydiaAT2OQiA8DPRRZyAKb9b6I2a6PxYklZD0gKg==",
"dev": true,
"peer": true,
"dependencies": {
"@types/unist": "^2.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/unified"
}
},
"node_modules/remark/node_modules/unist-util-visit": {
"version": "4.1.2",
"resolved": "https://registry.npmmirror.com/unist-util-visit/-/unist-util-visit-4.1.2.tgz",
"integrity": "sha512-MSd8OUGISqHdVvfY9TPhyK2VdUrPgxkUtWSuMHF6XAAFuL4LokseigBnZtPnJMu+FbynTkFNnFlyjxpVKujMRg==",
"dev": true,
"peer": true,
"dependencies": {
"@types/unist": "^2.0.0",
"unist-util-is": "^5.0.0",
"unist-util-visit-parents": "^5.1.1"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/unified"
}
},
"node_modules/remark/node_modules/unist-util-visit-parents": {
"version": "5.1.3",
"resolved": "https://registry.npmmirror.com/unist-util-visit-parents/-/unist-util-visit-parents-5.1.3.tgz",
"integrity": "sha512-x6+y8g7wWMyQhL1iZfhIPhDAs7Xwbn9nRosDXl7qoPTSCy0yNxnKc+hWokFifWQIDGi154rdUqKvbCa4+1kLhg==",
"dev": true,
"peer": true,
"dependencies": {
"@types/unist": "^2.0.0",
"unist-util-is": "^5.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/unified"
}
},
"node_modules/remark/node_modules/vfile": {
"version": "5.3.7",
"resolved": "https://registry.npmmirror.com/vfile/-/vfile-5.3.7.tgz",
"integrity": "sha512-r7qlzkgErKjobAmyNIkkSpizsFPYiUPuJb5pNW1RB4JcYVZhs4lIbVqk8XPk033CV/1z8ss5pkax8SuhGpcG8g==",
"dev": true,
"peer": true,
"dependencies": {
"@types/unist": "^2.0.0",
"is-buffer": "^2.0.0",
"unist-util-stringify-position": "^3.0.0",
"vfile-message": "^3.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/unified"
}
},
"node_modules/remark/node_modules/vfile-message": {
"version": "3.1.4",
"resolved": "https://registry.npmmirror.com/vfile-message/-/vfile-message-3.1.4.tgz",
"integrity": "sha512-fa0Z6P8HUrQN4BZaX05SIVXic+7kE3b05PWAtPuYP9QLHsLKYR7/AlLW3NtOrpXRLeawpDLMsVkmk5DG0NXgWw==",
"dev": true,
"peer": true,
"dependencies": {
"@types/unist": "^2.0.0",
"unist-util-stringify-position": "^3.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/unified"
}
},
"node_modules/remove-accents": {
"version": "0.4.2",
"resolved": "https://registry.npmmirror.com/remove-accents/-/remove-accents-0.4.2.tgz",
@ -24188,6 +25018,19 @@
"queue-microtask": "^1.2.2"
}
},
"node_modules/sade": {
"version": "1.8.1",
"resolved": "https://registry.npmmirror.com/sade/-/sade-1.8.1.tgz",
"integrity": "sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==",
"dev": true,
"peer": true,
"dependencies": {
"mri": "^1.1.0"
},
"engines": {
"node": ">=6"
}
},
"node_modules/safe-array-concat": {
"version": "1.1.2",
"resolved": "https://registry.npmmirror.com/safe-array-concat/-/safe-array-concat-1.1.2.tgz",
@ -26834,6 +27677,45 @@
"uuid": "dist/bin/uuid"
}
},
"node_modules/uvu": {
"version": "0.5.6",
"resolved": "https://registry.npmmirror.com/uvu/-/uvu-0.5.6.tgz",
"integrity": "sha512-+g8ENReyr8YsOc6fv/NVJs2vFdHBnBNdfE49rshrTzDWOlUx4Gq7KOS2GD8eqhy2j+Ejq29+SbKH8yjkAqXqoA==",
"dev": true,
"peer": true,
"dependencies": {
"dequal": "^2.0.0",
"diff": "^5.0.0",
"kleur": "^4.0.3",
"sade": "^1.7.3"
},
"bin": {
"uvu": "bin.js"
},
"engines": {
"node": ">=8"
}
},
"node_modules/uvu/node_modules/diff": {
"version": "5.2.0",
"resolved": "https://registry.npmmirror.com/diff/-/diff-5.2.0.tgz",
"integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==",
"dev": true,
"peer": true,
"engines": {
"node": ">=0.3.1"
}
},
"node_modules/uvu/node_modules/kleur": {
"version": "4.1.5",
"resolved": "https://registry.npmmirror.com/kleur/-/kleur-4.1.5.tgz",
"integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==",
"dev": true,
"peer": true,
"engines": {
"node": ">=6"
}
},
"node_modules/v8-compile-cache": {
"version": "2.4.0",
"resolved": "https://registry.npmmirror.com/v8-compile-cache/-/v8-compile-cache-2.4.0.tgz",

View File

@ -78,6 +78,7 @@
"@umijs/lint": "^4.1.1",
"@umijs/plugins": "^4.1.0",
"cross-env": "^7.0.3",
"html-loader": "^5.1.0",
"husky": "^9.0.11",
"jest": "^29.7.0",
"jest-environment-jsdom": "^29.7.0",
@ -86,6 +87,7 @@
"prettier-plugin-organize-imports": "^3.2.4",
"prettier-plugin-packagejson": "^2.4.9",
"react-dev-inspector": "^2.0.1",
"remark-loader": "^6.0.0",
"ts-node": "^10.9.2",
"typescript": "^5.0.3",
"umi-plugin-icons": "^0.1.1"

View File

@ -0,0 +1,6 @@
<svg t="1727608362384" class="icon" viewBox="0 0 1025 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4306"
width="24" height="24">
<path
d="M1019.520374 56.394706L966.393742 3.257862c-2.001695-2.001695-4.503815-2.87999-7.1387-2.879991s-5.137004 1.000848-7.148912 2.879991L856.749851 98.61414C814.520204 69.916363 765.396963 55.638964 716.283935 55.638964c-64.156382 0-128.312765 24.428855-177.30324 73.429543L411.280694 256.758295c-3.880838 3.880838-3.880838 10.274008 0 14.154847L751.74254 611.364776c2.001695 2.001695 4.514028 2.890203 7.1387 2.890203 2.512332 0 5.137004-1.000848 7.1387-2.890203l127.689788-127.689788c86.338436-86.460989 96.489892-220.166077 30.454367-317.646604l95.356279-95.366491c3.880838-3.993178 3.880838-10.386348 0-14.267187zM833.321844 423.409656l-74.430391 74.440604-234.075818-234.075818 74.430391-74.430391c31.199896-31.199896 72.806566-48.490052 117.037909-48.490051 44.231342 0 85.705247 17.167603 117.037909 48.490051 31.199896 31.199896 48.490052 72.806566 48.490051 117.037909 0 44.231342-17.290155 85.705247-48.490051 117.027696zM594.987317 554.980283c-3.880838-3.880838-10.274008-3.880838-14.154847 0l-83.458446 83.458446-113.15707-113.146858 83.580998-83.580999c3.891051-3.891051 3.891051-10.284221 0-14.165059l-45.610061-45.610061c-3.880838-3.891051-10.274008-3.891051-14.154846 0l-83.580999 83.580998-53.882374-53.882374c-2.001695-2.001695-4.514028-2.87999-7.1387-2.87999-2.512332 0-5.137004 1.000848-7.138699 2.87999L128.725037 539.313952C42.386601 625.774941 32.235145 759.480028 98.27067 856.970768L2.914392 952.33726c-3.880838 3.880838-3.880838 10.274008 0 14.154846l53.136844 53.126632c2.001695 2.001695 4.514028 2.87999 7.1387 2.87999 2.634885 0 5.137004-1.000848 7.1387-2.87999l95.366491-95.356279c42.219434 28.697777 91.352888 42.985389 140.465916 42.985389 64.156382 0 128.312765-24.439068 177.30324-73.429543l127.689789-127.689788c3.880838-3.891051 3.880838-10.274008 0-14.154847l-53.882374-53.882374 83.580998-83.580998c3.880838-3.880838 3.880838-10.274008 0-14.154847l-45.865379-45.375168zM423.066186 833.665314c-31.199896 31.199896-72.806566 48.490052-117.037908 48.490051-44.231342 0-85.705247-17.167603-117.037909-48.490051-31.199896-31.199896-48.490052-72.806566-48.490052-117.037909 0-44.231342 17.167603-85.71546 48.490052-117.037909l74.430391-74.430391 234.075817 234.075818-74.430391 74.430391z m0 0"
fill="#2C2C2C" p-id="4307"></path>
</svg>

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

@ -12,9 +12,9 @@ const ChatApiKeyModal = ({
dialogId,
hideModal,
idKey,
}: IModalProps<any> & { dialogId: string; idKey: string }) => {
}: IModalProps<any> & { dialogId?: string; idKey: string }) => {
const { createToken, removeToken, tokenList, listLoading, creatingLoading } =
useOperateApiKey(dialogId, idKey);
useOperateApiKey(idKey, dialogId);
const { t } = useTranslate('chat');
const columns: TableProps<IToken>['columns'] = [
@ -36,9 +36,7 @@ const ChatApiKeyModal = ({
render: (_, record) => (
<Space size="middle">
<CopyToClipboard text={record.token}></CopyToClipboard>
<DeleteOutlined
onClick={() => removeToken(record.token, record.tenant_id)}
/>
<DeleteOutlined onClick={() => removeToken(record.token)} />
</Space>
),
},
@ -60,8 +58,13 @@ const ChatApiKeyModal = ({
dataSource={tokenList}
rowKey={'token'}
loading={listLoading}
pagination={false}
/>
<Button onClick={createToken} loading={creatingLoading}>
<Button
onClick={createToken}
loading={creatingLoading}
disabled={tokenList.length > 0}
>
{t('createNewKey')}
</Button>
</Modal>

View File

@ -0,0 +1,64 @@
import HightLightMarkdown from '@/components/highlight-markdown';
import { useSetModalState, useTranslate } from '@/hooks/common-hooks';
import { Button, Card, Flex, Space } from 'antd';
import apiDoc from '../../../../../docs/references/api.md';
import ChatApiKeyModal from '../chat-api-key-modal';
import EmbedModal from '../embed-modal';
import { usePreviewChat, useShowEmbedModal } from '../hooks';
import BackendServiceApi from './backend-service-api';
const ApiContent = ({
id,
idKey,
hideChatPreviewCard = false,
}: {
id?: string;
idKey: string;
hideChatPreviewCard?: boolean;
}) => {
const { t } = useTranslate('chat');
const {
visible: apiKeyVisible,
hideModal: hideApiKeyModal,
showModal: showApiKeyModal,
} = useSetModalState();
const { embedVisible, hideEmbedModal, showEmbedModal, embedToken } =
useShowEmbedModal(idKey, id);
const { handlePreview } = usePreviewChat(idKey, id);
return (
<div>
<Flex vertical gap={'middle'}>
<BackendServiceApi show={showApiKeyModal}></BackendServiceApi>
{!hideChatPreviewCard && (
<Card title={`${name} Web App`}>
<Flex gap={8} vertical>
<Space size={'middle'}>
<Button onClick={handlePreview}>{t('preview')}</Button>
<Button onClick={showEmbedModal}>{t('embedded')}</Button>
</Space>
</Flex>
</Card>
)}
<HightLightMarkdown>{apiDoc}</HightLightMarkdown>
</Flex>
{apiKeyVisible && (
<ChatApiKeyModal
hideModal={hideApiKeyModal}
dialogId={id}
idKey={idKey}
></ChatApiKeyModal>
)}
{embedVisible && (
<EmbedModal
token={embedToken}
visible={embedVisible}
hideModal={hideEmbedModal}
></EmbedModal>
)}
</div>
);
};
export default ApiContent;

View File

@ -0,0 +1,35 @@
import { Button, Card, Flex, Space, Typography } from 'antd';
import { useTranslate } from '@/hooks/common-hooks';
import styles from './index.less';
const { Paragraph } = Typography;
const BackendServiceApi = ({ show }: { show(): void }) => {
const { t } = useTranslate('chat');
return (
<Card
title={
<Space size={'large'}>
<span>RAGFlow API</span>
<Button onClick={show} type="primary">
{t('apiKey')}
</Button>
</Space>
}
>
<Flex gap={8} align="center">
<b>{t('backendServiceApi')}</b>
<Paragraph
copyable={{ text: `${location.origin}/v1/api/` }}
className={styles.apiLinkText}
>
{location.origin}/v1/api/
</Paragraph>
</Flex>
</Card>
);
};
export default BackendServiceApi;

View File

@ -13,9 +13,7 @@
padding-left: 60px;
padding-bottom: 20px;
}
.linkText {
border-radius: 6px;
padding: 6px 10px;
background-color: #eff8ff;
border: 1px;
.apiLinkText {
.linkText();
margin: 0 !important;
}

View File

@ -1,65 +1,15 @@
import LineChart from '@/components/line-chart';
import { useFetchNextStats } from '@/hooks/chat-hooks';
import { useSetModalState, useTranslate } from '@/hooks/common-hooks';
import { useTranslate } from '@/hooks/common-hooks';
import { IModalProps } from '@/interfaces/common';
import { IStats } from '@/interfaces/database/chat';
import { formatDate } from '@/utils/date';
import { Button, Card, DatePicker, Flex, Modal, Space, Typography } from 'antd';
import { RangePickerProps } from 'antd/es/date-picker';
import dayjs from 'dayjs';
import camelCase from 'lodash/camelCase';
import ChatApiKeyModal from '../chat-api-key-modal';
import EmbedModal from '../embed-modal';
import {
usePreviewChat,
useSelectChartStatsList,
useShowEmbedModal,
} from '../hooks';
import styles from './index.less';
const { Paragraph } = Typography;
const { RangePicker } = DatePicker;
const StatsLineChart = ({ statsType }: { statsType: keyof IStats }) => {
const { t } = useTranslate('chat');
const chartList = useSelectChartStatsList();
const list =
chartList[statsType]?.map((x) => ({
...x,
xAxis: formatDate(x.xAxis),
})) ?? [];
return (
<div className={styles.chartItem}>
<b className={styles.chartLabel}>{t(camelCase(statsType))}</b>
<LineChart data={list}></LineChart>
</div>
);
};
import { Modal } from 'antd';
import ApiContent from './api-content';
const ChatOverviewModal = ({
visible,
hideModal,
id,
name = '',
idKey,
}: IModalProps<any> & { id: string; name?: string; idKey: string }) => {
const { t } = useTranslate('chat');
const {
visible: apiKeyVisible,
hideModal: hideApiKeyModal,
showModal: showApiKeyModal,
} = useSetModalState();
const { embedVisible, hideEmbedModal, showEmbedModal, embedToken } =
useShowEmbedModal(id, idKey);
const { pickerValue, setPickerValue } = useFetchNextStats();
const disabledDate: RangePickerProps['disabledDate'] = (current) => {
return current && current > dayjs().endOf('day');
};
const { handlePreview } = usePreviewChat(id, idKey);
return (
<>
@ -72,69 +22,7 @@ const ChatOverviewModal = ({
width={'100vw'}
okText={t('close', { keyPrefix: 'common' })}
>
<Flex vertical gap={'middle'}>
<Card title={t('backendServiceApi')}>
<Flex gap={8} vertical>
{t('serviceApiEndpoint')}
<Paragraph
copyable={{ text: `${location.origin}/v1/api/` }}
className={styles.linkText}
>
{location.origin}/v1/api/
</Paragraph>
</Flex>
<Space size={'middle'}>
<Button onClick={showApiKeyModal}>{t('apiKey')}</Button>
<a
href={
'https://github.com/infiniflow/ragflow/blob/main/docs/references/api.md'
}
target="_blank"
rel="noreferrer"
>
<Button>{t('apiReference')}</Button>
</a>
</Space>
</Card>
<Card title={`${name} Web App`}>
<Flex gap={8} vertical>
<Space size={'middle'}>
<Button onClick={handlePreview}>{t('preview')}</Button>
<Button onClick={showEmbedModal}>{t('embedded')}</Button>
</Space>
</Flex>
</Card>
<Space>
<b>{t('dateRange')}</b>
<RangePicker
disabledDate={disabledDate}
value={pickerValue}
onChange={setPickerValue}
allowClear={false}
/>
</Space>
<div className={styles.chartWrapper}>
<StatsLineChart statsType={'pv'}></StatsLineChart>
<StatsLineChart statsType={'round'}></StatsLineChart>
<StatsLineChart statsType={'speed'}></StatsLineChart>
<StatsLineChart statsType={'thumb_up'}></StatsLineChart>
<StatsLineChart statsType={'tokens'}></StatsLineChart>
<StatsLineChart statsType={'uv'}></StatsLineChart>
</div>
</Flex>
{apiKeyVisible && (
<ChatApiKeyModal
hideModal={hideApiKeyModal}
dialogId={id}
idKey={idKey}
></ChatApiKeyModal>
)}
<EmbedModal
token={embedToken}
visible={embedVisible}
hideModal={hideEmbedModal}
></EmbedModal>
<ApiContent id={id} idKey={idKey}></ApiContent>
</Modal>
</>
);

View File

@ -0,0 +1,40 @@
import LineChart from '@/components/line-chart';
import { useTranslate } from '@/hooks/common-hooks';
import { IStats } from '@/interfaces/database/chat';
import { formatDate } from '@/utils/date';
import camelCase from 'lodash/camelCase';
import { useSelectChartStatsList } from '../hooks';
import styles from './index.less';
const StatsLineChart = ({ statsType }: { statsType: keyof IStats }) => {
const { t } = useTranslate('chat');
const chartList = useSelectChartStatsList();
const list =
chartList[statsType]?.map((x) => ({
...x,
xAxis: formatDate(x.xAxis),
})) ?? [];
return (
<div className={styles.chartItem}>
<b className={styles.chartLabel}>{t(camelCase(statsType))}</b>
<LineChart data={list}></LineChart>
</div>
);
};
const StatsChart = () => {
return (
<div className={styles.chartWrapper}>
<StatsLineChart statsType={'pv'}></StatsLineChart>
<StatsLineChart statsType={'round'}></StatsLineChart>
<StatsLineChart statsType={'speed'}></StatsLineChart>
<StatsLineChart statsType={'thumb_up'}></StatsLineChart>
<StatsLineChart statsType={'tokens'}></StatsLineChart>
<StatsLineChart statsType={'uv'}></StatsLineChart>
</div>
);
};
export default StatsChart;

View File

@ -1,31 +1,31 @@
import { SharedFrom } from '@/constants/chat';
import {
useCreateNextToken,
useFetchTokenList,
useRemoveNextToken,
} from '@/hooks/chat-hooks';
import {
useSetModalState,
useShowDeleteConfirm,
useTranslate,
} from '@/hooks/common-hooks';
import {
useCreateSystemToken,
useFetchSystemTokenList,
useRemoveSystemToken,
} from '@/hooks/user-setting-hooks';
import { IStats } from '@/interfaces/database/chat';
import { useQueryClient } from '@tanstack/react-query';
import { message } from 'antd';
import { useCallback } from 'react';
export const useOperateApiKey = (dialogId: string, idKey: string) => {
const { removeToken } = useRemoveNextToken();
const { createToken, loading: creatingLoading } = useCreateNextToken();
const { data: tokenList, loading: listLoading } = useFetchTokenList({
export const useOperateApiKey = (idKey: string, dialogId?: string) => {
const { removeToken } = useRemoveSystemToken();
const { createToken, loading: creatingLoading } = useCreateSystemToken();
const { data: tokenList, loading: listLoading } = useFetchSystemTokenList({
[idKey]: dialogId,
});
const showDeleteConfirm = useShowDeleteConfirm();
const onRemoveToken = (token: string, tenantId: string) => {
const onRemoveToken = (token: string) => {
showDeleteConfirm({
onOk: () => removeToken({ dialogId, tokens: [token], tenantId }),
onOk: () => removeToken(token),
});
};
@ -49,7 +49,7 @@ type ChartStatsType = {
export const useSelectChartStatsList = (): ChartStatsType => {
const queryClient = useQueryClient();
const data = queryClient.getQueriesData({ queryKey: ['fetchStats'] });
const stats: IStats = data[0][1] as IStats;
const stats: IStats = (data.length > 0 ? data[0][1] : {}) as IStats;
return Object.keys(stats).reduce((pre, cur) => {
const item = stats[cur as keyof IStats];
@ -77,10 +77,12 @@ const getUrlWithToken = (token: string, from: string = 'chat') => {
return `${protocol}//${host}/chat/share?shared_id=${token}&from=${from}`;
};
const useFetchTokenListBeforeOtherStep = (dialogId: string, idKey: string) => {
const useFetchTokenListBeforeOtherStep = (idKey: string, dialogId?: string) => {
const { showTokenEmptyError } = useShowTokenEmptyError();
const { data: tokenList, refetch } = useFetchTokenList({ [idKey]: dialogId });
const { data: tokenList, refetch } = useFetchSystemTokenList({
[idKey]: dialogId,
});
const token =
Array.isArray(tokenList) && tokenList.length > 0 ? tokenList[0].token : '';
@ -102,7 +104,7 @@ const useFetchTokenListBeforeOtherStep = (dialogId: string, idKey: string) => {
};
};
export const useShowEmbedModal = (dialogId: string, idKey: string) => {
export const useShowEmbedModal = (idKey: string, dialogId?: string) => {
const {
visible: embedVisible,
hideModal: hideEmbedModal,
@ -110,8 +112,8 @@ export const useShowEmbedModal = (dialogId: string, idKey: string) => {
} = useSetModalState();
const { handleOperate, token } = useFetchTokenListBeforeOtherStep(
dialogId,
idKey,
dialogId,
);
const handleShowEmbedModal = useCallback(async () => {
@ -129,8 +131,8 @@ export const useShowEmbedModal = (dialogId: string, idKey: string) => {
};
};
export const usePreviewChat = (dialogId: string, idKey: string) => {
const { handleOperate } = useFetchTokenListBeforeOtherStep(dialogId, idKey);
export const usePreviewChat = (idKey: string, dialogId?: string) => {
const { handleOperate } = useFetchTokenListBeforeOtherStep(idKey, dialogId);
const open = useCallback(
(t: string) => {

View File

@ -1,4 +1,19 @@
.text {
white-space: pre-wrap; // https://stackoverflow.com/questions/60332183/new-line-with-react-markdown
.chunkText;
font-size: 16px;
li {
padding: 4px 0px;
}
p {
white-space: pre-wrap; // https://stackoverflow.com/questions/60332183/new-line-with-react-markdown
}
}
.code {
padding: 3px 6px 6px;
margin: 0;
white-space: break-spaces;
background-color: rgba(129, 139, 152, 0.12);
border-radius: 4px;
color: rgb(31, 35, 40);
}

View File

@ -1,6 +1,6 @@
import classNames from 'classnames';
import Markdown from 'react-markdown';
import SyntaxHighlighter from 'react-syntax-highlighter';
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';
import rehypeRaw from 'rehype-raw';
import remarkGfm from 'remark-gfm';
@ -22,11 +22,16 @@ const HightLightMarkdown = ({
const { children, className, node, ...rest } = props;
const match = /language-(\w+)/.exec(className || '');
return match ? (
<SyntaxHighlighter {...rest} PreTag="div" language={match[1]}>
<SyntaxHighlighter
{...rest}
PreTag="div"
language={match[1]}
// style={dark}
>
{String(children).replace(/\n$/, '')}
</SyntaxHighlighter>
) : (
<code {...rest} className={className}>
<code {...rest} className={`${className} ${styles.code}`}>
{children}
</code>
);

View File

@ -41,6 +41,12 @@ export const fileIconMap = {
export const LanguageList = ['English', 'Chinese', 'Traditional Chinese'];
export const LanguageMap = {
English: 'English',
Chinese: '简体中文',
'Traditional Chinese': '繁體中文',
};
export const LanguageTranslationMap = {
English: 'en',
Chinese: 'zh',

View File

@ -5,6 +5,7 @@ export enum UserSettingRouteKey {
Password = 'password',
Model = 'model',
System = 'system',
Api = 'api',
Team = 'team',
Logout = 'logout',
}

View File

@ -441,7 +441,7 @@ export const useRemoveNextToken = () => {
mutationKey: ['removeToken'],
mutationFn: async (params: {
tenantId: string;
dialogId: string;
dialogId?: string;
tokens: string[];
}) => {
const { data } = await chatService.removeToken(params);

View File

@ -1,5 +1,6 @@
import { LanguageTranslationMap } from '@/constants/common';
import { ResponseGetType } from '@/interfaces/database/base';
import { IToken } from '@/interfaces/database/chat';
import { ITenantInfo } from '@/interfaces/database/knowledge';
import { ISystemStatus, IUserInfo } from '@/interfaces/database/user-setting';
import userService from '@/services/user-service';
@ -152,3 +153,65 @@ export const useFetchSystemStatus = () => {
loading,
};
};
export const useFetchSystemTokenList = (params: Record<string, any>) => {
const {
data,
isFetching: loading,
refetch,
} = useQuery<IToken[]>({
queryKey: ['fetchSystemTokenList', params],
initialData: [],
gcTime: 0,
queryFn: async () => {
const { data } = await userService.listToken(params);
return data?.data ?? [];
},
});
return { data, loading, refetch };
};
export const useRemoveSystemToken = () => {
const queryClient = useQueryClient();
const { t } = useTranslation();
const {
data,
isPending: loading,
mutateAsync,
} = useMutation({
mutationKey: ['removeSystemToken'],
mutationFn: async (token: string) => {
const { data } = await userService.removeToken({}, token);
if (data.retcode === 0) {
message.success(t('message.deleted'));
queryClient.invalidateQueries({ queryKey: ['fetchSystemTokenList'] });
}
return data?.data ?? [];
},
});
return { data, loading, removeToken: mutateAsync };
};
export const useCreateSystemToken = () => {
const queryClient = useQueryClient();
const {
data,
isPending: loading,
mutateAsync,
} = useMutation({
mutationKey: ['createSystemToken'],
mutationFn: async (params: Record<string, any>) => {
const { data } = await userService.createToken(params);
if (data.retcode === 0) {
queryClient.invalidateQueries({ queryKey: ['fetchSystemTokenList'] });
}
return data?.data ?? [];
},
});
return { data, loading, createToken: mutateAsync };
};

View File

@ -5,7 +5,7 @@ import camelCase from 'lodash/camelCase';
import React from 'react';
import User from '../user';
import { LanguageList } from '@/constants/common';
import { LanguageList, LanguageMap } from '@/constants/common';
import { useChangeLanguage } from '@/hooks/logic-hooks';
import { useFetchUserInfo } from '@/hooks/user-setting-hooks';
import styled from './index.less';
@ -35,7 +35,7 @@ const RightToolBar = () => {
const items: MenuProps['items'] = LanguageList.map((x) => ({
key: x,
label: <span>{t(camelCase(x))}</span>,
label: <span>{LanguageMap[x as keyof typeof LanguageMap]}</span>,
})).reduce<MenuProps['items']>((pre, cur) => {
return [...pre!, { type: 'divider' }, cur];
}, []);

View File

@ -1,3 +1,8 @@
.tableCell() {
padding: 6px 13px;
border: 1px solid #d1d9e0;
}
.chunkText() {
em {
color: red;
@ -5,6 +10,8 @@
}
table {
width: 100%;
box-sizing: border-box;
border-collapse: collapse;
}
caption {
@ -17,8 +24,13 @@
}
th {
color: #fff;
background-color: @blurBackground;
// color: #fff;
// background-color: @blurBackground;
.tableCell;
}
td {
.tableCell;
}
td:hover {
@ -56,3 +68,10 @@
overflow: hidden;
text-overflow: ellipsis;
}
.linkText() {
border-radius: 6px;
padding: 6px 10px;
background-color: #eff8ff;
border: 1px;
}

View File

@ -400,7 +400,7 @@ The above is the content you need to summarize.`,
quoteTip: 'Should the source of the original text be displayed?',
selfRag: 'Self-RAG',
selfRagTip: 'Please refer to: https://huggingface.co/papers/2310.11511',
overview: 'Chat Bot API',
overview: 'Chat ID',
pv: 'Number of messages',
uv: 'Active user number',
speed: 'Token output speed',
@ -413,7 +413,7 @@ The above is the content you need to summarize.`,
apiKey: 'API Key',
apiReference: 'API Documents',
dateRange: 'Date Range:',
backendServiceApi: 'Backend service API',
backendServiceApi: 'API Server',
createNewKey: 'Create new key',
created: 'Created',
action: 'Action',
@ -451,6 +451,7 @@ The above is the content you need to summarize.`,
team: 'Team',
system: 'System',
logout: 'Log out',
api: 'API',
username: 'Username',
usernameMessage: 'Please input your username!',
photo: 'Your photo',

View File

@ -371,7 +371,7 @@ export default {
quoteTip: '是否應該顯示原文出處?',
selfRag: 'Self-RAG',
selfRagTip: '請參考: https://huggingface.co/papers/2310.11511',
overview: '聊天 API',
overview: '聊天 ID',
pv: '消息數',
uv: '活躍用戶數',
speed: 'Token 輸出速度',
@ -384,7 +384,7 @@ export default {
apiKey: 'API 鍵',
apiReference: 'API 文檔',
dateRange: '日期範圍:',
backendServiceApi: '後端服務 API',
backendServiceApi: 'API 伺服器',
createNewKey: '創建新密鑰',
created: '創建於',
action: '操作',

View File

@ -388,7 +388,7 @@ export default {
quoteTip: '是否应该显示原文出处?',
selfRag: 'Self-RAG',
selfRagTip: '请参考: https://huggingface.co/papers/2310.11511',
overview: '聊天 API',
overview: '聊天 ID',
pv: '消息数',
uv: '活跃用户数',
speed: 'Token 输出速度',
@ -401,7 +401,7 @@ export default {
apiKey: 'API 键',
apiReference: 'API 文档',
dateRange: '日期范围:',
backendServiceApi: '后端服务 API',
backendServiceApi: 'API 服务器',
createNewKey: '创建新密钥',
created: '创建于',
action: '操作',

View File

@ -0,0 +1,11 @@
import ApiContent from '@/components/api-service/chat-overview-modal/api-content';
const ApiPage = () => {
return (
<div>
<ApiContent idKey="dialogId"></ApiContent>
</div>
);
};
export default ApiPage;

View File

@ -0,0 +1,3 @@
.id {
.linkText();
}

View File

@ -0,0 +1,34 @@
import { useTranslate } from '@/hooks/common-hooks';
import { IModalProps } from '@/interfaces/common';
import { Modal, Typography } from 'antd';
import styles from './index.less';
const { Paragraph } = Typography;
const ChatIdModal = ({
visible,
hideModal,
id,
}: IModalProps<any> & { id: string; name?: string; idKey: string }) => {
const { t } = useTranslate('chat');
return (
<>
<Modal
title={t('overview')}
open={visible}
onCancel={hideModal}
cancelButtonProps={{ style: { display: 'none' } }}
onOk={hideModal}
okText={t('close', { keyPrefix: 'common' })}
>
<Paragraph copyable={{ text: id }} className={styles.id}>
{id}
</Paragraph>
</Modal>
</>
);
};
export default ChatIdModal;

View File

@ -1,6 +1,6 @@
import { ReactComponent as ChatAppCube } from '@/assets/svg/chat-app-cube.svg';
import RenameModal from '@/components/rename-modal';
import { CloudOutlined, DeleteOutlined, EditOutlined } from '@ant-design/icons';
import { DeleteOutlined, EditOutlined, KeyOutlined } from '@ant-design/icons';
import {
Avatar,
Button,
@ -29,7 +29,6 @@ import {
useSelectDerivedConversationList,
} from './hooks';
import ChatOverviewModal from '@/components/api-service/chat-overview-modal';
import SvgIcon from '@/components/svg-icon';
import {
useClickConversationCard,
@ -40,6 +39,7 @@ import {
import { useSetModalState, useTranslate } from '@/hooks/common-hooks';
import { useSetSelectedRecord } from '@/hooks/logic-hooks';
import { IDialog } from '@/interfaces/database/chat';
import ChatIdModal from './chat-id-modal';
import styles from './index.less';
const { Text } = Typography;
@ -190,7 +190,7 @@ const Chat = () => {
onClick: handleShowOverviewModal(dialog),
label: (
<Space>
<CloudOutlined />
<KeyOutlined />
{t('overview')}
</Space>
),
@ -367,13 +367,13 @@ const Chat = () => {
loading={conversationRenameLoading}
></RenameModal>
{overviewVisible && (
<ChatOverviewModal
<ChatIdModal
visible={overviewVisible}
hideModal={hideOverviewModal}
id={currentRecord.id}
name={currentRecord.name}
idKey="dialogId"
></ChatOverviewModal>
></ChatIdModal>
)}
</Flex>
);

View File

@ -1,3 +1,4 @@
import { ReactComponent as ApiIcon } from '@/assets/svg/api.svg';
import { ReactComponent as LogoutIcon } from '@/assets/svg/logout.svg';
import { ReactComponent as ModelIcon } from '@/assets/svg/model-providers.svg';
import { ReactComponent as PasswordIcon } from '@/assets/svg/password.svg';
@ -13,6 +14,7 @@ export const UserSettingIconMap = {
[UserSettingRouteKey.System]: <MonitorOutlined style={{ fontSize: 24 }} />,
[UserSettingRouteKey.Team]: <TeamIcon />,
[UserSettingRouteKey.Logout]: <LogoutIcon />,
[UserSettingRouteKey.Api]: <ApiIcon />,
};
export * from '@/constants/setting';

View File

@ -0,0 +1,7 @@
.apiWrapper {
width: 100%;
div[class^='chartWrapper'] {
height: auto !important;
}
}

View File

@ -0,0 +1,13 @@
import ApiContent from '@/components/api-service/chat-overview-modal/api-content';
import styles from './index.less';
const ApiPage = () => {
return (
<div className={styles.apiWrapper}>
<ApiContent idKey="dialogId" hideChatPreviewCard></ApiContent>
</div>
);
};
export default ApiPage;

View File

@ -77,6 +77,10 @@ const routes = [
path: '/user-setting/system',
component: '@/pages/user-setting/setting-system',
},
{
path: '/user-setting/api',
component: '@/pages/user-setting/setting-api',
},
],
},
{

View File

@ -19,6 +19,9 @@ const {
deleteFactory,
getSystemStatus,
getSystemVersion,
getSystemTokenList,
removeSystemToken,
createSystemToken,
} = api;
const methods = {
@ -86,6 +89,18 @@ const methods = {
url: deleteFactory,
method: 'post',
},
listToken: {
url: getSystemTokenList,
method: 'get',
},
createToken: {
url: createSystemToken,
method: 'post',
},
removeToken: {
url: removeSystemToken,
method: 'delete',
},
} as const;
const userService = registerServer<keyof typeof methods>(methods, request);

View File

@ -94,6 +94,10 @@ export default {
// system
getSystemVersion: `${api_host}/system/version`,
getSystemStatus: `${api_host}/system/status`,
getSystemTokenList: `${api_host}/system/token_list`,
createSystemToken: `${api_host}/system/new_token`,
listSystemToken: `${api_host}/system/token_list`,
removeSystemToken: `${api_host}/system/token`,
// flow
listTemplates: `${api_host}/canvas/templates`,