From 246ee973ec64cc1f4ee9edd06e8cc870beece542 Mon Sep 17 00:00:00 2001 From: archer <545436317@qq.com> Date: Fri, 19 May 2023 10:26:30 +0800 Subject: [PATCH] feat: share unlogin.perf: link format and model ui --- package.json | 1 - pnpm-lock.yaml | 185 --------- public/docs/versionIntro.md | 5 +- src/api/plugins/kb.ts | 2 + src/components/Markdown/index.tsx | 7 +- src/pages/api/chat/shareChat/chat.ts | 2 +- src/pages/api/chat/shareChat/create.ts | 3 +- src/pages/api/chat/shareChat/init.ts | 3 +- src/pages/api/plugins/kb/detail.ts | 46 +++ src/pages/kb/components/Detail.tsx | 22 +- .../detail/components/ModelEditForm.tsx | 350 +++++++++--------- src/pages/model/components/detail/index.tsx | 24 +- src/service/utils/auth.ts | 3 +- src/store/user.ts | 16 +- src/utils/tools.ts | 8 +- 15 files changed, 283 insertions(+), 394 deletions(-) create mode 100644 src/pages/api/plugins/kb/detail.ts diff --git a/package.json b/package.json index d159fe0e0..000ed0323 100644 --- a/package.json +++ b/package.json @@ -51,7 +51,6 @@ "react-syntax-highlighter": "^15.5.0", "redis": "^4.6.5", "rehype-katex": "^6.0.2", - "rehype-raw": "^6.1.1", "remark-gfm": "^3.0.1", "remark-math": "^5.1.1", "sass": "^1.58.3", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ce568375d..d9de80e66 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -59,7 +59,6 @@ specifiers: react-syntax-highlighter: ^15.5.0 redis: ^4.6.5 rehype-katex: ^6.0.2 - rehype-raw: ^6.1.1 remark-gfm: ^3.0.1 remark-math: ^5.1.1 sass: ^1.58.3 @@ -110,7 +109,6 @@ dependencies: react-syntax-highlighter: registry.npmmirror.com/react-syntax-highlighter/15.5.0_react@18.2.0 redis: registry.npmmirror.com/redis/4.6.5 rehype-katex: registry.npmmirror.com/rehype-katex/6.0.2 - rehype-raw: 6.1.1 remark-gfm: registry.npmmirror.com/remark-gfm/3.0.1 remark-math: registry.npmmirror.com/remark-math/5.1.1 sass: registry.npmmirror.com/sass/1.58.3 @@ -302,31 +300,15 @@ packages: '@types/unist': 2.0.6 dev: false - /@types/parse5/6.0.3: - resolution: {integrity: sha512-SuT16Q1K51EAVPz1K29DJ/sXjhSQ0zjvsypYJ6tlwVsRV9jwW5Adq2ch8Dq8kDBCkYnELS7N7VNCSB5nC56t/g==} - dev: false - /@types/unist/2.0.6: resolution: {integrity: sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ==} dev: false - /bail/2.0.2: - resolution: {integrity: sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==} - dev: false - - /comma-separated-tokens/2.0.3: - resolution: {integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==} - dev: false - /cookie/0.5.0: resolution: {integrity: sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==} engines: {node: '>= 0.6'} dev: false - /extend/3.0.2: - resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} - dev: false - /fsevents/2.3.2: resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} @@ -341,91 +323,6 @@ packages: dev: false optional: true - /hast-util-from-parse5/7.1.2: - resolution: {integrity: sha512-Nz7FfPBuljzsN3tCQ4kCBKqdNhQE2l0Tn+X1ubgKBPRoiDIu1mL08Cfw4k7q71+Duyaw7DXDN+VTAp4Vh3oCOw==} - dependencies: - '@types/hast': 2.3.4 - '@types/unist': 2.0.6 - hastscript: 7.2.0 - property-information: 6.2.0 - vfile: 5.3.7 - vfile-location: 4.1.0 - web-namespaces: 2.0.1 - dev: false - - /hast-util-parse-selector/3.1.1: - resolution: {integrity: sha512-jdlwBjEexy1oGz0aJ2f4GKMaVKkA9jwjr4MjAAI22E5fM/TXVZHuS5OpONtdeIkRKqAaryQ2E9xNQxijoThSZA==} - dependencies: - '@types/hast': 2.3.4 - dev: false - - /hast-util-raw/7.2.3: - resolution: {integrity: sha512-RujVQfVsOrxzPOPSzZFiwofMArbQke6DJjnFfceiEbFh7S05CbPt0cYN+A5YeD3pso0JQk6O1aHBnx9+Pm2uqg==} - dependencies: - '@types/hast': 2.3.4 - '@types/parse5': 6.0.3 - hast-util-from-parse5: 7.1.2 - hast-util-to-parse5: 7.1.0 - html-void-elements: 2.0.1 - parse5: 6.0.1 - unist-util-position: 4.0.4 - unist-util-visit: 4.1.2 - vfile: 5.3.7 - web-namespaces: 2.0.1 - zwitch: 2.0.4 - dev: false - - /hast-util-to-parse5/7.1.0: - resolution: {integrity: sha512-YNRgAJkH2Jky5ySkIqFXTQiaqcAtJyVE+D5lkN6CdtOqrnkLfGYYrEcKuHOJZlp+MwjSwuD3fZuawI+sic/RBw==} - dependencies: - '@types/hast': 2.3.4 - comma-separated-tokens: 2.0.3 - property-information: 6.2.0 - space-separated-tokens: 2.0.2 - web-namespaces: 2.0.1 - zwitch: 2.0.4 - dev: false - - /hastscript/7.2.0: - resolution: {integrity: sha512-TtYPq24IldU8iKoJQqvZOuhi5CyCQRAbvDOX0x1eW6rsHSxa/1i2CCiptNTotGHJ3VoHRGmqiv6/D3q113ikkw==} - dependencies: - '@types/hast': 2.3.4 - comma-separated-tokens: 2.0.3 - hast-util-parse-selector: 3.1.1 - property-information: 6.2.0 - space-separated-tokens: 2.0.2 - dev: false - - /html-void-elements/2.0.1: - resolution: {integrity: sha512-0quDb7s97CfemeJAnW9wC0hw78MtW7NU3hqtCD75g2vFlDLt36llsYD7uB7SUzojLMP24N5IatXf7ylGXiGG9A==} - dev: false - - /is-buffer/2.0.5: - resolution: {integrity: sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==} - engines: {node: '>=4'} - dev: false - - /is-plain-obj/4.1.0: - resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==} - engines: {node: '>=12'} - dev: false - - /parse5/6.0.1: - resolution: {integrity: sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==} - dev: false - - /property-information/6.2.0: - resolution: {integrity: sha512-kma4U7AFCTwpqq5twzC1YVIDXSqg6qQK6JN0smOw8fgRy1OkMi0CYSzFmsy6dnqSenamAtj0CyXMUJ1Mf6oROg==} - dev: false - - /rehype-raw/6.1.1: - resolution: {integrity: sha512-d6AKtisSRtDRX4aSPsJGTfnzrX2ZkHQLE5kiUuGOeEoLpbEulFF4hj0mLPbsa+7vmguDKOVVEQdHKDSwoaIDsQ==} - dependencies: - '@types/hast': 2.3.4 - hast-util-raw: 7.2.3 - unified: 10.1.2 - dev: false - /saslprep/1.0.3: resolution: {integrity: sha512-/MY/PEMbk2SuY5sScONwhUDsV2p77Znkb/q3nSVstq/yQzYJOH/Azh29p9oJLsl3LnQwSvZDKagDGBsBwSooag==} engines: {node: '>=6'} @@ -442,88 +339,6 @@ packages: dev: false optional: true - /space-separated-tokens/2.0.2: - resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==} - dev: false - - /trough/2.1.0: - resolution: {integrity: sha512-AqTiAOLcj85xS7vQ8QkAV41hPDIJ71XJB4RCUrzo/1GM2CQwhkJGaf9Hgr7BOugMRpgGUrqRg/DrBDl4H40+8g==} - dev: false - - /unified/10.1.2: - resolution: {integrity: sha512-pUSWAi/RAnVy1Pif2kAoeWNBa3JVrx0MId2LASj8G+7AiHWoKZNTomq6LG326T68U7/e263X6fTdcXIy7XnF7Q==} - dependencies: - '@types/unist': 2.0.6 - bail: 2.0.2 - extend: 3.0.2 - is-buffer: 2.0.5 - is-plain-obj: 4.1.0 - trough: 2.1.0 - vfile: 5.3.7 - dev: false - - /unist-util-is/5.2.0: - resolution: {integrity: sha512-Glt17jWwZeyqrFqOK0pF1Ded5U3yzJnFr8CG1GMjCWTp9zDo2p+cmD6pWbZU8AgM5WU3IzRv6+rBwhzsGh6hBQ==} - dev: false - - /unist-util-position/4.0.4: - resolution: {integrity: sha512-kUBE91efOWfIVBo8xzh/uZQ7p9ffYRtUbMRZBNFYwf0RK8koUMx6dGUfwylLOKmaT2cs4wSW96QoYUSXAyEtpg==} - dependencies: - '@types/unist': 2.0.6 - dev: false - - /unist-util-stringify-position/3.0.3: - resolution: {integrity: sha512-k5GzIBZ/QatR8N5X2y+drfpWG8IDBzdnVj6OInRNWm1oXrzydiaAT2OQiA8DPRRZyAKb9b6I2a6PxYklZD0gKg==} - dependencies: - '@types/unist': 2.0.6 - dev: false - - /unist-util-visit-parents/5.1.3: - resolution: {integrity: sha512-x6+y8g7wWMyQhL1iZfhIPhDAs7Xwbn9nRosDXl7qoPTSCy0yNxnKc+hWokFifWQIDGi154rdUqKvbCa4+1kLhg==} - dependencies: - '@types/unist': 2.0.6 - unist-util-is: 5.2.0 - dev: false - - /unist-util-visit/4.1.2: - resolution: {integrity: sha512-MSd8OUGISqHdVvfY9TPhyK2VdUrPgxkUtWSuMHF6XAAFuL4LokseigBnZtPnJMu+FbynTkFNnFlyjxpVKujMRg==} - dependencies: - '@types/unist': 2.0.6 - unist-util-is: 5.2.0 - unist-util-visit-parents: 5.1.3 - dev: false - - /vfile-location/4.1.0: - resolution: {integrity: sha512-YF23YMyASIIJXpktBa4vIGLJ5Gs88UB/XePgqPmTa7cDA+JeO3yclbpheQYCHjVHBn/yePzrXuygIL+xbvRYHw==} - dependencies: - '@types/unist': 2.0.6 - vfile: 5.3.7 - dev: false - - /vfile-message/3.1.4: - resolution: {integrity: sha512-fa0Z6P8HUrQN4BZaX05SIVXic+7kE3b05PWAtPuYP9QLHsLKYR7/AlLW3NtOrpXRLeawpDLMsVkmk5DG0NXgWw==} - dependencies: - '@types/unist': 2.0.6 - unist-util-stringify-position: 3.0.3 - dev: false - - /vfile/5.3.7: - resolution: {integrity: sha512-r7qlzkgErKjobAmyNIkkSpizsFPYiUPuJb5pNW1RB4JcYVZhs4lIbVqk8XPk033CV/1z8ss5pkax8SuhGpcG8g==} - dependencies: - '@types/unist': 2.0.6 - is-buffer: 2.0.5 - unist-util-stringify-position: 3.0.3 - vfile-message: 3.1.4 - dev: false - - /web-namespaces/2.0.1: - resolution: {integrity: sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==} - dev: false - - /zwitch/2.0.4: - resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==} - dev: false - registry.npmmirror.com/@alicloud/credentials/2.2.6: resolution: {integrity: sha512-jG+msY77dHmAF3x+8VTy7fEgORyXLHmDci8t92HeipBdCHsPptDegA++GEwKgR7f6G4wvafYt+aqMZ1iligdrQ==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@alicloud/credentials/-/credentials-2.2.6.tgz} name: '@alicloud/credentials' diff --git a/public/docs/versionIntro.md b/public/docs/versionIntro.md index b2f3af264..c4e202104 100644 --- a/public/docs/versionIntro.md +++ b/public/docs/versionIntro.md @@ -1,4 +1,3 @@ -### Fast GPT V3.6 +### Fast GPT V3.7 -- 新增 - 分享免登录聊天框。可以直接为模型生成一个分享链接,其他人可以通过这个链接直接使用对话。 -- 优化 - UI 细节。 +- 新增 - 知识库与 AI 助手对多对关系,一个知识库可以被多个 AI 助手关联,一个 AI 助手可以关联多个知识库。 diff --git a/src/api/plugins/kb.ts b/src/api/plugins/kb.ts index 3ba66c424..0b148c2c7 100644 --- a/src/api/plugins/kb.ts +++ b/src/api/plugins/kb.ts @@ -9,6 +9,8 @@ export type KbUpdateParams = { id: string; name: string; tags: string; avatar: s /* knowledge base */ export const getKbList = () => GET(`/plugins/kb/list`); +export const getKbById = (id: string) => GET(`/plugins/kb/detail?id=${id}`); + export const postCreateKb = (data: { name: string }) => POST(`/plugins/kb/create`, data); export const putKbById = (data: KbUpdateParams) => PUT(`/plugins/kb/update`, data); diff --git a/src/components/Markdown/index.tsx b/src/components/Markdown/index.tsx index 1db278935..fc25f7af3 100644 --- a/src/components/Markdown/index.tsx +++ b/src/components/Markdown/index.tsx @@ -2,12 +2,11 @@ import React, { memo, useMemo } from 'react'; import ReactMarkdown from 'react-markdown'; import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter'; import { Box, Flex, useColorModeValue } from '@chakra-ui/react'; -import { useCopyData, formatLinkTextToHtml } from '@/utils/tools'; +import { useCopyData, formatLinkText } from '@/utils/tools'; import Icon from '@/components/Icon'; import remarkGfm from 'remark-gfm'; import remarkMath from 'remark-math'; import rehypeKatex from 'rehype-katex'; -import rehypeRaw from 'rehype-raw'; import 'katex/dist/katex.min.css'; import styles from './index.module.scss'; @@ -25,7 +24,7 @@ const Markdown = ({ const { copyData } = useCopyData(); const formatSource = useMemo(() => { - return formatLink ? formatLinkTextToHtml(source) : source; + return formatLink ? formatLinkText(source) : source; }, [source, formatLink]); return ( @@ -34,7 +33,7 @@ const Markdown = ({ isChatting ? (source === '' ? styles.waitingAnimation : styles.animation) : '' }`} remarkPlugins={[remarkMath]} - rehypePlugins={[rehypeRaw, remarkGfm, rehypeKatex]} + rehypePlugins={[remarkGfm, rehypeKatex]} components={{ pre: 'div', code({ node, inline, className, children, ...props }) { diff --git a/src/pages/api/chat/shareChat/chat.ts b/src/pages/api/chat/shareChat/chat.ts index 689dd4cfe..4ce4403f0 100644 --- a/src/pages/api/chat/shareChat/chat.ts +++ b/src/pages/api/chat/shareChat/chat.ts @@ -33,7 +33,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) await connectToDatabase(); let startTime = Date.now(); - const { model, showModelDetail, userOpenAiKey, systemAuthKey, userId } = await authShareChat({ + const { model, userOpenAiKey, systemAuthKey, userId } = await authShareChat({ shareId, password }); diff --git a/src/pages/api/chat/shareChat/create.ts b/src/pages/api/chat/shareChat/create.ts index 4d4617d16..754c7e2c7 100644 --- a/src/pages/api/chat/shareChat/create.ts +++ b/src/pages/api/chat/shareChat/create.ts @@ -16,7 +16,8 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) const userId = await authToken(req); await authModel({ modelId, - userId + userId, + authOwner: false }); const { _id } = await ShareChat.create({ diff --git a/src/pages/api/chat/shareChat/init.ts b/src/pages/api/chat/shareChat/init.ts index 548f65500..df3438456 100644 --- a/src/pages/api/chat/shareChat/init.ts +++ b/src/pages/api/chat/shareChat/init.ts @@ -36,7 +36,8 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) // 校验使用权限 const { model } = await authModel({ modelId: shareChat.modelId, - userId: String(shareChat.userId) + userId: String(shareChat.userId), + authOwner: false }); jsonRes(res, { diff --git a/src/pages/api/plugins/kb/detail.ts b/src/pages/api/plugins/kb/detail.ts new file mode 100644 index 000000000..315c56bf4 --- /dev/null +++ b/src/pages/api/plugins/kb/detail.ts @@ -0,0 +1,46 @@ +import type { NextApiRequest, NextApiResponse } from 'next'; +import { jsonRes } from '@/service/response'; +import { connectToDatabase, KB } from '@/service/mongo'; +import { authToken } from '@/service/utils/auth'; + +export default async function handler(req: NextApiRequest, res: NextApiResponse) { + try { + const { id } = req.query as { + id: string; + }; + + if (!id) { + throw new Error('缺少参数'); + } + + // 凭证校验 + const userId = await authToken(req); + + await connectToDatabase(); + + const data = await KB.findOne({ + _id: id, + userId + }); + + if (!data) { + throw new Error('kb is not exist'); + } + + jsonRes(res, { + data: { + _id: data._id, + avatar: data.avatar, + name: data.name, + userId: data.userId, + updateTime: data.updateTime, + tags: data.tags.join(' ') + } + }); + } catch (err) { + jsonRes(res, { + code: 500, + error: err + }); + } +} diff --git a/src/pages/kb/components/Detail.tsx b/src/pages/kb/components/Detail.tsx index 4e4c7df3d..c04e5d338 100644 --- a/src/pages/kb/components/Detail.tsx +++ b/src/pages/kb/components/Detail.tsx @@ -24,18 +24,18 @@ import { useSelectFile } from '@/hooks/useSelectFile'; import { useConfirm } from '@/hooks/useConfirm'; import { compressImg } from '@/utils/file'; import DataCard from './DataCard'; +import { getErrText } from '@/utils/tools'; const Detail = ({ kbId }: { kbId: string }) => { const { toast } = useToast(); const router = useRouter(); const InputRef = useRef(null); - const { setLastKbId, KbDetail, getKbDetail, loadKbList, myKbList } = useUserStore(); - const { Loading, setIsLoading } = useLoading(); + const { setLastKbId, kbDetail, getKbDetail, loadKbList, myKbList } = useUserStore(); const [btnLoading, setBtnLoading] = useState(false); const [refresh, setRefresh] = useState(false); const { getValues, formState, setValue, reset, register, handleSubmit } = useForm({ - defaultValues: KbDetail + defaultValues: kbDetail }); const { openConfirm, ConfirmChild } = useConfirm({ content: '确认删除该知识库?数据将无法恢复,请确认!' @@ -46,7 +46,7 @@ const Detail = ({ kbId }: { kbId: string }) => { multiple: false }); - const { isLoading } = useQuery([kbId, myKbList], () => getKbDetail(kbId), { + useQuery([kbId, myKbList], () => getKbDetail(kbId), { onSuccess(res) { kbId && setLastKbId(kbId); if (res) { @@ -58,17 +58,18 @@ const Detail = ({ kbId }: { kbId: string }) => { }, onError(err: any) { toast({ - title: err?.message || '获取AI助手异常', + title: getErrText(err, '获取AI助手异常'), status: 'error' }); + loadKbList(true); setLastKbId(''); - router.replace('/model'); + router.replace(`/kb?kbId=${myKbList[0]?._id || ''}`); } }); /* 点击删除 */ const onclickDelKb = useCallback(async () => { - setIsLoading(true); + setBtnLoading(true); try { await delKbById(kbId); toast({ @@ -83,8 +84,8 @@ const Detail = ({ kbId }: { kbId: string }) => { status: 'error' }); } - setIsLoading(false); - }, [setIsLoading, kbId, toast, router, myKbList, loadKbList]); + setBtnLoading(false); + }, [setBtnLoading, kbId, toast, router, myKbList, loadKbList]); const saveSubmitSuccess = useCallback( async (data: KbItemType) => { @@ -155,7 +156,7 @@ const Detail = ({ kbId }: { kbId: string }) => { 知识库信息 - {KbDetail._id && ( + {kbDetail._id && ( <>