diff --git a/web/.umirc.ts b/web/.umirc.ts index 80cb6c8e9..f9a42973b 100644 --- a/web/.umirc.ts +++ b/web/.umirc.ts @@ -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; + }, }); diff --git a/web/package-lock.json b/web/package-lock.json index 3ea22a384..ea0b007b2 100644 --- a/web/package-lock.json +++ b/web/package-lock.json @@ -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", diff --git a/web/package.json b/web/package.json index bab2d0241..e4ecbb501 100644 --- a/web/package.json +++ b/web/package.json @@ -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" diff --git a/web/src/assets/svg/api.svg b/web/src/assets/svg/api.svg new file mode 100644 index 000000000..db088dd74 --- /dev/null +++ b/web/src/assets/svg/api.svg @@ -0,0 +1,6 @@ + + + \ No newline at end of file diff --git a/web/src/components/api-service/chat-api-key-modal/index.tsx b/web/src/components/api-service/chat-api-key-modal/index.tsx index 46e6761a6..e586d3727 100644 --- a/web/src/components/api-service/chat-api-key-modal/index.tsx +++ b/web/src/components/api-service/chat-api-key-modal/index.tsx @@ -12,9 +12,9 @@ const ChatApiKeyModal = ({ dialogId, hideModal, idKey, -}: IModalProps & { dialogId: string; idKey: string }) => { +}: IModalProps & { dialogId?: string; idKey: string }) => { const { createToken, removeToken, tokenList, listLoading, creatingLoading } = - useOperateApiKey(dialogId, idKey); + useOperateApiKey(idKey, dialogId); const { t } = useTranslate('chat'); const columns: TableProps['columns'] = [ @@ -36,9 +36,7 @@ const ChatApiKeyModal = ({ render: (_, record) => ( - removeToken(record.token, record.tenant_id)} - /> + removeToken(record.token)} /> ), }, @@ -60,8 +58,13 @@ const ChatApiKeyModal = ({ dataSource={tokenList} rowKey={'token'} loading={listLoading} + pagination={false} /> - + 0} + > {t('createNewKey')} diff --git a/web/src/components/api-service/chat-overview-modal/api-content.tsx b/web/src/components/api-service/chat-overview-modal/api-content.tsx new file mode 100644 index 000000000..786273f15 --- /dev/null +++ b/web/src/components/api-service/chat-overview-modal/api-content.tsx @@ -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 ( + + + + {!hideChatPreviewCard && ( + + + + {t('preview')} + {t('embedded')} + + + + )} + {apiDoc} + + {apiKeyVisible && ( + + )} + {embedVisible && ( + + )} + + ); +}; + +export default ApiContent; diff --git a/web/src/components/api-service/chat-overview-modal/backend-service-api.tsx b/web/src/components/api-service/chat-overview-modal/backend-service-api.tsx new file mode 100644 index 000000000..b5ea34adb --- /dev/null +++ b/web/src/components/api-service/chat-overview-modal/backend-service-api.tsx @@ -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 ( + + RAGFlow API + + {t('apiKey')} + + + } + > + + {t('backendServiceApi')} + + {location.origin}/v1/api/ + + + + ); +}; + +export default BackendServiceApi; diff --git a/web/src/components/api-service/chat-overview-modal/index.less b/web/src/components/api-service/chat-overview-modal/index.less index eeccc2f98..c923c4df7 100644 --- a/web/src/components/api-service/chat-overview-modal/index.less +++ b/web/src/components/api-service/chat-overview-modal/index.less @@ -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; } diff --git a/web/src/components/api-service/chat-overview-modal/index.tsx b/web/src/components/api-service/chat-overview-modal/index.tsx index 559d11d8c..f31b05c82 100644 --- a/web/src/components/api-service/chat-overview-modal/index.tsx +++ b/web/src/components/api-service/chat-overview-modal/index.tsx @@ -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 ( - - {t(camelCase(statsType))} - - - ); -}; +import { Modal } from 'antd'; +import ApiContent from './api-content'; const ChatOverviewModal = ({ visible, hideModal, id, - name = '', idKey, }: IModalProps & { 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' })} > - - - - {t('serviceApiEndpoint')} - - {location.origin}/v1/api/ - - - - {t('apiKey')} - - {t('apiReference')} - - - - - - - {t('preview')} - {t('embedded')} - - - - - - {t('dateRange')} - - - - - - - - - - - - {apiKeyVisible && ( - - )} - + > ); diff --git a/web/src/components/api-service/chat-overview-modal/stats-chart.tsx b/web/src/components/api-service/chat-overview-modal/stats-chart.tsx new file mode 100644 index 000000000..ed910d538 --- /dev/null +++ b/web/src/components/api-service/chat-overview-modal/stats-chart.tsx @@ -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 ( + + {t(camelCase(statsType))} + + + ); +}; + +const StatsChart = () => { + return ( + + + + + + + + + ); +}; + +export default StatsChart; diff --git a/web/src/components/api-service/hooks.ts b/web/src/components/api-service/hooks.ts index d16d5553b..006cbe43e 100644 --- a/web/src/components/api-service/hooks.ts +++ b/web/src/components/api-service/hooks.ts @@ -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) => { diff --git a/web/src/components/highlight-markdown/index.less b/web/src/components/highlight-markdown/index.less index c0798c064..325a0c31b 100644 --- a/web/src/components/highlight-markdown/index.less +++ b/web/src/components/highlight-markdown/index.less @@ -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); } diff --git a/web/src/components/highlight-markdown/index.tsx b/web/src/components/highlight-markdown/index.tsx index 57eda455e..490626caa 100644 --- a/web/src/components/highlight-markdown/index.tsx +++ b/web/src/components/highlight-markdown/index.tsx @@ -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 ? ( - + {String(children).replace(/\n$/, '')} ) : ( - + {children} ); diff --git a/web/src/constants/common.ts b/web/src/constants/common.ts index 876647dcf..2c16044cc 100644 --- a/web/src/constants/common.ts +++ b/web/src/constants/common.ts @@ -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', diff --git a/web/src/constants/setting.ts b/web/src/constants/setting.ts index e27244ff0..e09dc4c9f 100644 --- a/web/src/constants/setting.ts +++ b/web/src/constants/setting.ts @@ -5,6 +5,7 @@ export enum UserSettingRouteKey { Password = 'password', Model = 'model', System = 'system', + Api = 'api', Team = 'team', Logout = 'logout', } diff --git a/web/src/hooks/chat-hooks.ts b/web/src/hooks/chat-hooks.ts index f9e89066a..00980a735 100644 --- a/web/src/hooks/chat-hooks.ts +++ b/web/src/hooks/chat-hooks.ts @@ -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); diff --git a/web/src/hooks/user-setting-hooks.tsx b/web/src/hooks/user-setting-hooks.tsx index 688da7172..68cd9e482 100644 --- a/web/src/hooks/user-setting-hooks.tsx +++ b/web/src/hooks/user-setting-hooks.tsx @@ -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) => { + const { + data, + isFetching: loading, + refetch, + } = useQuery({ + 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) => { + const { data } = await userService.createToken(params); + if (data.retcode === 0) { + queryClient.invalidateQueries({ queryKey: ['fetchSystemTokenList'] }); + } + return data?.data ?? []; + }, + }); + + return { data, loading, createToken: mutateAsync }; +}; diff --git a/web/src/layouts/components/right-toolbar/index.tsx b/web/src/layouts/components/right-toolbar/index.tsx index e636dfa84..267bc23c4 100644 --- a/web/src/layouts/components/right-toolbar/index.tsx +++ b/web/src/layouts/components/right-toolbar/index.tsx @@ -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: {t(camelCase(x))}, + label: {LanguageMap[x as keyof typeof LanguageMap]}, })).reduce((pre, cur) => { return [...pre!, { type: 'divider' }, cur]; }, []); diff --git a/web/src/less/mixins.less b/web/src/less/mixins.less index a80a06935..7501bdbb2 100644 --- a/web/src/less/mixins.less +++ b/web/src/less/mixins.less @@ -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; +} diff --git a/web/src/locales/en.ts b/web/src/locales/en.ts index 48e40fb79..247e586db 100644 --- a/web/src/locales/en.ts +++ b/web/src/locales/en.ts @@ -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', diff --git a/web/src/locales/zh-traditional.ts b/web/src/locales/zh-traditional.ts index 67a8fca29..9b57dd75a 100644 --- a/web/src/locales/zh-traditional.ts +++ b/web/src/locales/zh-traditional.ts @@ -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: '操作', diff --git a/web/src/locales/zh.ts b/web/src/locales/zh.ts index f72d8512d..687cc9cd9 100644 --- a/web/src/locales/zh.ts +++ b/web/src/locales/zh.ts @@ -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: '操作', diff --git a/web/src/pages/api/index.tsx b/web/src/pages/api/index.tsx new file mode 100644 index 000000000..c41ef489f --- /dev/null +++ b/web/src/pages/api/index.tsx @@ -0,0 +1,11 @@ +import ApiContent from '@/components/api-service/chat-overview-modal/api-content'; + +const ApiPage = () => { + return ( + + + + ); +}; + +export default ApiPage; diff --git a/web/src/pages/chat/chat-id-modal/index.less b/web/src/pages/chat/chat-id-modal/index.less new file mode 100644 index 000000000..c95b34c95 --- /dev/null +++ b/web/src/pages/chat/chat-id-modal/index.less @@ -0,0 +1,3 @@ +.id { + .linkText(); +} diff --git a/web/src/pages/chat/chat-id-modal/index.tsx b/web/src/pages/chat/chat-id-modal/index.tsx new file mode 100644 index 000000000..9ea92a180 --- /dev/null +++ b/web/src/pages/chat/chat-id-modal/index.tsx @@ -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 & { id: string; name?: string; idKey: string }) => { + const { t } = useTranslate('chat'); + + return ( + <> + + + {id} + + + > + ); +}; + +export default ChatIdModal; diff --git a/web/src/pages/chat/index.tsx b/web/src/pages/chat/index.tsx index 3a87a8395..550a81381 100644 --- a/web/src/pages/chat/index.tsx +++ b/web/src/pages/chat/index.tsx @@ -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: ( - + {t('overview')} ), @@ -367,13 +367,13 @@ const Chat = () => { loading={conversationRenameLoading} > {overviewVisible && ( - + > )} ); diff --git a/web/src/pages/user-setting/constants.tsx b/web/src/pages/user-setting/constants.tsx index e8360487e..1fa4c859e 100644 --- a/web/src/pages/user-setting/constants.tsx +++ b/web/src/pages/user-setting/constants.tsx @@ -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]: , [UserSettingRouteKey.Team]: , [UserSettingRouteKey.Logout]: , + [UserSettingRouteKey.Api]: , }; export * from '@/constants/setting'; diff --git a/web/src/pages/user-setting/setting-api/index.less b/web/src/pages/user-setting/setting-api/index.less new file mode 100644 index 000000000..772530dd9 --- /dev/null +++ b/web/src/pages/user-setting/setting-api/index.less @@ -0,0 +1,7 @@ +.apiWrapper { + width: 100%; + + div[class^='chartWrapper'] { + height: auto !important; + } +} diff --git a/web/src/pages/user-setting/setting-api/index.tsx b/web/src/pages/user-setting/setting-api/index.tsx new file mode 100644 index 000000000..8b07b8953 --- /dev/null +++ b/web/src/pages/user-setting/setting-api/index.tsx @@ -0,0 +1,13 @@ +import ApiContent from '@/components/api-service/chat-overview-modal/api-content'; + +import styles from './index.less'; + +const ApiPage = () => { + return ( + + + + ); +}; + +export default ApiPage; diff --git a/web/src/routes.ts b/web/src/routes.ts index eb1ed77b3..dfaec0b40 100644 --- a/web/src/routes.ts +++ b/web/src/routes.ts @@ -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', + }, ], }, { diff --git a/web/src/services/user-service.ts b/web/src/services/user-service.ts index f68f2d306..99617bae0 100644 --- a/web/src/services/user-service.ts +++ b/web/src/services/user-service.ts @@ -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(methods, request); diff --git a/web/src/utils/api.ts b/web/src/utils/api.ts index 94e1a5840..99639f4b5 100644 --- a/web/src/utils/api.ts +++ b/web/src/utils/api.ts @@ -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`,
+ {children} ); diff --git a/web/src/constants/common.ts b/web/src/constants/common.ts index 876647dcf..2c16044cc 100644 --- a/web/src/constants/common.ts +++ b/web/src/constants/common.ts @@ -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', diff --git a/web/src/constants/setting.ts b/web/src/constants/setting.ts index e27244ff0..e09dc4c9f 100644 --- a/web/src/constants/setting.ts +++ b/web/src/constants/setting.ts @@ -5,6 +5,7 @@ export enum UserSettingRouteKey { Password = 'password', Model = 'model', System = 'system', + Api = 'api', Team = 'team', Logout = 'logout', } diff --git a/web/src/hooks/chat-hooks.ts b/web/src/hooks/chat-hooks.ts index f9e89066a..00980a735 100644 --- a/web/src/hooks/chat-hooks.ts +++ b/web/src/hooks/chat-hooks.ts @@ -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); diff --git a/web/src/hooks/user-setting-hooks.tsx b/web/src/hooks/user-setting-hooks.tsx index 688da7172..68cd9e482 100644 --- a/web/src/hooks/user-setting-hooks.tsx +++ b/web/src/hooks/user-setting-hooks.tsx @@ -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) => { + const { + data, + isFetching: loading, + refetch, + } = useQuery({ + 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) => { + const { data } = await userService.createToken(params); + if (data.retcode === 0) { + queryClient.invalidateQueries({ queryKey: ['fetchSystemTokenList'] }); + } + return data?.data ?? []; + }, + }); + + return { data, loading, createToken: mutateAsync }; +}; diff --git a/web/src/layouts/components/right-toolbar/index.tsx b/web/src/layouts/components/right-toolbar/index.tsx index e636dfa84..267bc23c4 100644 --- a/web/src/layouts/components/right-toolbar/index.tsx +++ b/web/src/layouts/components/right-toolbar/index.tsx @@ -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: {t(camelCase(x))}, + label: {LanguageMap[x as keyof typeof LanguageMap]}, })).reduce((pre, cur) => { return [...pre!, { type: 'divider' }, cur]; }, []); diff --git a/web/src/less/mixins.less b/web/src/less/mixins.less index a80a06935..7501bdbb2 100644 --- a/web/src/less/mixins.less +++ b/web/src/less/mixins.less @@ -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; +} diff --git a/web/src/locales/en.ts b/web/src/locales/en.ts index 48e40fb79..247e586db 100644 --- a/web/src/locales/en.ts +++ b/web/src/locales/en.ts @@ -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', diff --git a/web/src/locales/zh-traditional.ts b/web/src/locales/zh-traditional.ts index 67a8fca29..9b57dd75a 100644 --- a/web/src/locales/zh-traditional.ts +++ b/web/src/locales/zh-traditional.ts @@ -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: '操作', diff --git a/web/src/locales/zh.ts b/web/src/locales/zh.ts index f72d8512d..687cc9cd9 100644 --- a/web/src/locales/zh.ts +++ b/web/src/locales/zh.ts @@ -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: '操作', diff --git a/web/src/pages/api/index.tsx b/web/src/pages/api/index.tsx new file mode 100644 index 000000000..c41ef489f --- /dev/null +++ b/web/src/pages/api/index.tsx @@ -0,0 +1,11 @@ +import ApiContent from '@/components/api-service/chat-overview-modal/api-content'; + +const ApiPage = () => { + return ( + + + + ); +}; + +export default ApiPage; diff --git a/web/src/pages/chat/chat-id-modal/index.less b/web/src/pages/chat/chat-id-modal/index.less new file mode 100644 index 000000000..c95b34c95 --- /dev/null +++ b/web/src/pages/chat/chat-id-modal/index.less @@ -0,0 +1,3 @@ +.id { + .linkText(); +} diff --git a/web/src/pages/chat/chat-id-modal/index.tsx b/web/src/pages/chat/chat-id-modal/index.tsx new file mode 100644 index 000000000..9ea92a180 --- /dev/null +++ b/web/src/pages/chat/chat-id-modal/index.tsx @@ -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 & { id: string; name?: string; idKey: string }) => { + const { t } = useTranslate('chat'); + + return ( + <> + + + {id} + + + > + ); +}; + +export default ChatIdModal; diff --git a/web/src/pages/chat/index.tsx b/web/src/pages/chat/index.tsx index 3a87a8395..550a81381 100644 --- a/web/src/pages/chat/index.tsx +++ b/web/src/pages/chat/index.tsx @@ -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: ( - + {t('overview')} ), @@ -367,13 +367,13 @@ const Chat = () => { loading={conversationRenameLoading} > {overviewVisible && ( - + > )} ); diff --git a/web/src/pages/user-setting/constants.tsx b/web/src/pages/user-setting/constants.tsx index e8360487e..1fa4c859e 100644 --- a/web/src/pages/user-setting/constants.tsx +++ b/web/src/pages/user-setting/constants.tsx @@ -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]: , [UserSettingRouteKey.Team]: , [UserSettingRouteKey.Logout]: , + [UserSettingRouteKey.Api]: , }; export * from '@/constants/setting'; diff --git a/web/src/pages/user-setting/setting-api/index.less b/web/src/pages/user-setting/setting-api/index.less new file mode 100644 index 000000000..772530dd9 --- /dev/null +++ b/web/src/pages/user-setting/setting-api/index.less @@ -0,0 +1,7 @@ +.apiWrapper { + width: 100%; + + div[class^='chartWrapper'] { + height: auto !important; + } +} diff --git a/web/src/pages/user-setting/setting-api/index.tsx b/web/src/pages/user-setting/setting-api/index.tsx new file mode 100644 index 000000000..8b07b8953 --- /dev/null +++ b/web/src/pages/user-setting/setting-api/index.tsx @@ -0,0 +1,13 @@ +import ApiContent from '@/components/api-service/chat-overview-modal/api-content'; + +import styles from './index.less'; + +const ApiPage = () => { + return ( + + + + ); +}; + +export default ApiPage; diff --git a/web/src/routes.ts b/web/src/routes.ts index eb1ed77b3..dfaec0b40 100644 --- a/web/src/routes.ts +++ b/web/src/routes.ts @@ -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', + }, ], }, { diff --git a/web/src/services/user-service.ts b/web/src/services/user-service.ts index f68f2d306..99617bae0 100644 --- a/web/src/services/user-service.ts +++ b/web/src/services/user-service.ts @@ -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(methods, request); diff --git a/web/src/utils/api.ts b/web/src/utils/api.ts index 94e1a5840..99639f4b5 100644 --- a/web/src/utils/api.ts +++ b/web/src/utils/api.ts @@ -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`,
{children}