mirror of
https://github.com/labring/FastGPT.git
synced 2025-07-29 09:44:47 +00:00
4.6.4-alpha (#582)
This commit is contained in:
@@ -2,7 +2,10 @@ import type { NextApiRequest, NextApiResponse } from 'next';
|
||||
import { jsonRes } from '@fastgpt/service/common/response';
|
||||
import { connectToDatabase } from '@/service/mongo';
|
||||
import { authCert } from '@fastgpt/service/support/permission/auth/common';
|
||||
import { delFileById, getGFSCollection } from '@fastgpt/service/common/file/gridfs/controller';
|
||||
import {
|
||||
delFileByFileIdList,
|
||||
getGFSCollection
|
||||
} from '@fastgpt/service/common/file/gridfs/controller';
|
||||
import { addLog } from '@fastgpt/service/common/mongo/controller';
|
||||
import { MongoDatasetCollection } from '@fastgpt/service/core/dataset/collection/schema';
|
||||
import { delay } from '@fastgpt/global/common/system/utils';
|
||||
@@ -77,7 +80,7 @@ export async function checkFiles(start: Date, end: Date, limit: number) {
|
||||
|
||||
// 3. if not found, delete file
|
||||
if (hasCollection === 0) {
|
||||
await delFileById({ bucketName: 'dataset', fileId: String(_id) });
|
||||
await delFileByFileIdList({ bucketName: 'dataset', fileIdList: [String(_id)] });
|
||||
console.log('delete file', _id);
|
||||
deleteFileAmount++;
|
||||
}
|
||||
|
@@ -4,6 +4,7 @@ import { connectToDatabase } from '@/service/mongo';
|
||||
import { authFileToken } from '@fastgpt/service/support/permission/controller';
|
||||
import { detect } from 'jschardet';
|
||||
import { getDownloadStream, getFileById } from '@fastgpt/service/common/file/gridfs/controller';
|
||||
import { CommonErrEnum } from '@fastgpt/global/common/error/code/common';
|
||||
|
||||
export default async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
|
||||
try {
|
||||
@@ -22,6 +23,10 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
|
||||
getDownloadStream({ bucketName, fileId })
|
||||
]);
|
||||
|
||||
if (!file) {
|
||||
return Promise.reject(CommonErrEnum.fileNotFound);
|
||||
}
|
||||
|
||||
// get encoding
|
||||
let buffers: Buffer = Buffer.from([]);
|
||||
for await (const chunk of encodeStream) {
|
||||
|
@@ -1,21 +1,22 @@
|
||||
import type { NextApiRequest, NextApiResponse } from 'next';
|
||||
import { jsonRes } from '@fastgpt/service/common/response';
|
||||
import { connectToDatabase } from '@/service/mongo';
|
||||
import { authCert } from '@fastgpt/service/support/permission/auth/common';
|
||||
import { authCertOrShareId } from '@fastgpt/service/support/permission/auth/common';
|
||||
import { uploadMongoImg } from '@fastgpt/service/common/file/image/controller';
|
||||
|
||||
type Props = { base64Img: string; expiredTime?: Date };
|
||||
import { UploadImgProps } from '@fastgpt/global/common/file/api';
|
||||
|
||||
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
try {
|
||||
await connectToDatabase();
|
||||
const { teamId } = await authCert({ req, authToken: true });
|
||||
const { base64Img, expiredTime } = req.body as Props;
|
||||
const { base64Img, expiredTime, metadata, shareId } = req.body as UploadImgProps;
|
||||
|
||||
const { teamId } = await authCertOrShareId({ req, shareId, authToken: true });
|
||||
|
||||
const data = await uploadMongoImg({
|
||||
teamId,
|
||||
base64Img,
|
||||
expiredTime
|
||||
expiredTime,
|
||||
metadata
|
||||
});
|
||||
|
||||
jsonRes(res, { data });
|
||||
|
@@ -4,13 +4,14 @@ import { connectToDatabase } from '@/service/mongo';
|
||||
import type { CreateQuestionGuideParams } from '@/global/core/ai/api.d';
|
||||
import { pushQuestionGuideBill } from '@/service/support/wallet/bill/push';
|
||||
import { createQuestionGuide } from '@fastgpt/service/core/ai/functions/createQuestionGuide';
|
||||
import { authCertAndShareId } from '@fastgpt/service/support/permission/auth/common';
|
||||
import { authCertOrShareId } from '@fastgpt/service/support/permission/auth/common';
|
||||
|
||||
export default async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
|
||||
try {
|
||||
await connectToDatabase();
|
||||
const { messages, shareId } = req.body as CreateQuestionGuideParams;
|
||||
const { tmbId, teamId } = await authCertAndShareId({
|
||||
|
||||
const { tmbId, teamId } = await authCertOrShareId({
|
||||
req,
|
||||
authToken: true,
|
||||
shareId
|
||||
|
@@ -4,6 +4,9 @@ import { connectToDatabase } from '@/service/mongo';
|
||||
import { MongoApp } from '@fastgpt/service/core/app/schema';
|
||||
import type { AppUpdateParams } from '@fastgpt/global/core/app/api';
|
||||
import { authApp } from '@fastgpt/service/support/permission/auth/app';
|
||||
import { FlowNodeTypeEnum } from '@fastgpt/global/core/module/node/constant';
|
||||
import { ModuleInputKeyEnum } from '@fastgpt/global/core/module/constants';
|
||||
import { getChatModel } from '@/service/core/ai/model';
|
||||
|
||||
/* 获取我的模型 */
|
||||
export default async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
|
||||
@@ -20,6 +23,36 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
|
||||
// 凭证校验
|
||||
await authApp({ req, authToken: true, appId, per: permission ? 'owner' : 'w' });
|
||||
|
||||
// check modules
|
||||
// 1. dataset search limit, less than model quoteMaxToken
|
||||
if (modules) {
|
||||
let maxTokens = 3000;
|
||||
|
||||
modules.forEach((item) => {
|
||||
if (item.flowType === FlowNodeTypeEnum.chatNode) {
|
||||
const model =
|
||||
item.inputs.find((item) => item.key === ModuleInputKeyEnum.aiModel)?.value || '';
|
||||
const chatModel = getChatModel(model);
|
||||
const quoteMaxToken = chatModel.quoteMaxToken || 3000;
|
||||
|
||||
maxTokens = Math.max(maxTokens, quoteMaxToken);
|
||||
}
|
||||
});
|
||||
|
||||
modules.forEach((item) => {
|
||||
if (item.flowType === FlowNodeTypeEnum.datasetSearchNode) {
|
||||
item.inputs.forEach((input) => {
|
||||
if (input.key === ModuleInputKeyEnum.datasetLimit) {
|
||||
const val = input.value as number;
|
||||
if (val > maxTokens) {
|
||||
input.value = maxTokens;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 更新模型
|
||||
await MongoApp.updateOne(
|
||||
{
|
||||
|
@@ -10,6 +10,10 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
|
||||
await connectToDatabase();
|
||||
const { chatId, contentId, shareId, outLinkUid } = req.query as DeleteChatItemProps;
|
||||
|
||||
if (!contentId || !chatId) {
|
||||
return jsonRes(res);
|
||||
}
|
||||
|
||||
await autChatCrud({
|
||||
req,
|
||||
authToken: true,
|
||||
|
@@ -4,7 +4,7 @@ import { connectToDatabase } from '@/service/mongo';
|
||||
import { GetChatSpeechProps } from '@/global/core/chat/api.d';
|
||||
import { text2Speech } from '@fastgpt/service/core/ai/audio/speech';
|
||||
import { pushAudioSpeechBill } from '@/service/support/wallet/bill/push';
|
||||
import { authCertAndShareId } from '@fastgpt/service/support/permission/auth/common';
|
||||
import { authCertOrShareId } from '@fastgpt/service/support/permission/auth/common';
|
||||
import { authType2BillSource } from '@/service/support/wallet/bill/utils';
|
||||
import { getAudioSpeechModel } from '@/service/core/ai/model';
|
||||
import { MongoTTSBuffer } from '@fastgpt/service/common/buffer/tts/schema';
|
||||
@@ -25,7 +25,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
|
||||
throw new Error('model or voice not found');
|
||||
}
|
||||
|
||||
const { teamId, tmbId, authType } = await authCertAndShareId({ req, authToken: true, shareId });
|
||||
const { teamId, tmbId, authType } = await authCertOrShareId({ req, authToken: true, shareId });
|
||||
|
||||
const ttsModel = getAudioSpeechModel(ttsConfig.model);
|
||||
const voiceData = ttsModel.voices?.find((item) => item.value === ttsConfig.voice);
|
||||
|
@@ -24,13 +24,13 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
|
||||
});
|
||||
|
||||
// find all delete id
|
||||
const collections = await findCollectionAndChild(collectionId, '_id metadata');
|
||||
const collections = await findCollectionAndChild(collectionId, '_id fileId');
|
||||
const delIdList = collections.map((item) => item._id);
|
||||
|
||||
// delete
|
||||
await delCollectionRelevantData({
|
||||
collectionIds: delIdList,
|
||||
fileIds: collections.map((item) => item.metadata?.fileId).filter(Boolean)
|
||||
fileIds: collections.map((item) => item?.fileId || '').filter(Boolean)
|
||||
});
|
||||
|
||||
// delete collection
|
||||
|
@@ -4,7 +4,6 @@ import { connectToDatabase } from '@/service/mongo';
|
||||
import { authDatasetCollection } from '@fastgpt/service/support/permission/auth/dataset';
|
||||
import { loadingOneChunkCollection } from '@fastgpt/service/core/dataset/collection/utils';
|
||||
import { delCollectionRelevantData } from '@fastgpt/service/core/dataset/data/controller';
|
||||
import { createOneCollection } from '@fastgpt/service/core/dataset/collection/controller';
|
||||
import { MongoDatasetCollection } from '@fastgpt/service/core/dataset/collection/schema';
|
||||
import { DatasetCollectionTypeEnum } from '@fastgpt/global/core/dataset/constant';
|
||||
import { DatasetErrEnum } from '@fastgpt/global/common/error/code/dataset';
|
||||
|
@@ -15,8 +15,11 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
|
||||
throw new Error('缺少参数');
|
||||
}
|
||||
|
||||
// 凭证校验
|
||||
await authDataset({ req, authToken: true, datasetId: id, per: 'owner' });
|
||||
if (permission) {
|
||||
await authDataset({ req, authToken: true, datasetId: id, per: 'owner' });
|
||||
} else {
|
||||
await authDataset({ req, authToken: true, datasetId: id, per: 'w' });
|
||||
}
|
||||
|
||||
await MongoDataset.findOneAndUpdate(
|
||||
{
|
||||
|
@@ -21,7 +21,6 @@ import type { AppSimpleEditFormType } from '@fastgpt/global/core/app/type.d';
|
||||
import { chatModelList, simpleModeTemplates } from '@/web/common/system/staticData';
|
||||
import { formatPrice } from '@fastgpt/global/support/wallet/bill/tools';
|
||||
import { chatNodeSystemPromptTip, welcomeTextTip } from '@fastgpt/global/core/module/template/tip';
|
||||
import type { VariableItemType } from '@fastgpt/global/core/module/type.d';
|
||||
import type { ModuleItemType } from '@fastgpt/global/core/module/type';
|
||||
import { useRequest } from '@/web/common/hooks/useRequest';
|
||||
import { useConfirm } from '@/web/common/hooks/useConfirm';
|
||||
@@ -67,7 +66,6 @@ function ConfigForm({
|
||||
}) {
|
||||
const theme = useTheme();
|
||||
const router = useRouter();
|
||||
const { toast } = useToast();
|
||||
const { t } = useTranslation();
|
||||
const { appDetail, updateAppDetail } = useAppStore();
|
||||
const { loadAllDatasets, allDatasets } = useDatasetStore();
|
||||
@@ -124,6 +122,13 @@ function ConfigForm({
|
||||
[getValues, refresh]
|
||||
);
|
||||
|
||||
const tokenLimit = useMemo(() => {
|
||||
return (
|
||||
chatModelList.find((item) => item.model === getValues('aiSettings.model'))?.quoteMaxToken ||
|
||||
3000
|
||||
);
|
||||
}, [getValues, refresh]);
|
||||
|
||||
const { mutate: onSubmitSave, isLoading: isSaving } = useRequest({
|
||||
mutationFn: async (data: AppSimpleEditFormType) => {
|
||||
const modules = await postForm2Modules(data, data.templateId);
|
||||
@@ -361,8 +366,8 @@ function ConfigForm({
|
||||
)}
|
||||
</Flex>
|
||||
<Flex mt={1} color={'myGray.600'} fontSize={['sm', 'md']}>
|
||||
{t('core.dataset.Similarity')}: {getValues('dataset.similarity')},{' '}
|
||||
{t('core.dataset.Search Top K')}: {getValues('dataset.limit')}
|
||||
{t('core.dataset.search.Min Similarity')}: {getValues('dataset.similarity')},{' '}
|
||||
{t('core.dataset.search.Max Tokens')}: {getValues('dataset.limit')}
|
||||
{getValues('dataset.searchEmptyText') === ''
|
||||
? ''
|
||||
: t('core.dataset.Set Empty Result Tip')}
|
||||
@@ -458,6 +463,7 @@ function ConfigForm({
|
||||
{isOpenDatasetParams && (
|
||||
<DatasetParamsModal
|
||||
{...getValues('dataset')}
|
||||
maxTokens={tokenLimit}
|
||||
onClose={onCloseKbParams}
|
||||
onSuccess={(e) => {
|
||||
setValue('dataset', {
|
||||
|
@@ -15,6 +15,7 @@ import Loading from '@/components/Loading';
|
||||
import SimpleEdit from './components/SimpleEdit';
|
||||
import { serviceSideProps } from '@/web/common/utils/i18n';
|
||||
import { useAppStore } from '@/web/core/app/store/useAppStore';
|
||||
import Head from 'next/head';
|
||||
|
||||
const AdEdit = dynamic(() => import('./components/AdEdit'), {
|
||||
loading: () => <Loading />
|
||||
@@ -92,90 +93,95 @@ const AppDetail = ({ currentTab }: { currentTab: `${TabEnum}` }) => {
|
||||
});
|
||||
|
||||
return (
|
||||
<PageContainer>
|
||||
<Flex flexDirection={['column', 'row']} h={'100%'}>
|
||||
{/* pc tab */}
|
||||
<Box
|
||||
display={['none', 'flex']}
|
||||
flexDirection={'column'}
|
||||
p={4}
|
||||
w={'180px'}
|
||||
borderRight={theme.borders.base}
|
||||
>
|
||||
<Flex mb={4} alignItems={'center'}>
|
||||
<Avatar src={appDetail.avatar} w={'34px'} borderRadius={'lg'} />
|
||||
<Box ml={2} fontWeight={'bold'} fontSize={'sm'}>
|
||||
<>
|
||||
<Head>
|
||||
<title>{appDetail.name}</title>
|
||||
</Head>
|
||||
<PageContainer>
|
||||
<Flex flexDirection={['column', 'row']} h={'100%'}>
|
||||
{/* pc tab */}
|
||||
<Box
|
||||
display={['none', 'flex']}
|
||||
flexDirection={'column'}
|
||||
p={4}
|
||||
w={'180px'}
|
||||
borderRight={theme.borders.base}
|
||||
>
|
||||
<Flex mb={4} alignItems={'center'}>
|
||||
<Avatar src={appDetail.avatar} w={'34px'} borderRadius={'lg'} />
|
||||
<Box ml={2} fontWeight={'bold'} fontSize={'sm'}>
|
||||
{appDetail.name}
|
||||
</Box>
|
||||
</Flex>
|
||||
<SideTabs
|
||||
flex={1}
|
||||
mx={'auto'}
|
||||
mt={2}
|
||||
w={'100%'}
|
||||
list={tabList}
|
||||
activeId={currentTab}
|
||||
onChange={(e: any) => {
|
||||
if (e === 'startChat') {
|
||||
router.push(`/chat?appId=${appId}`);
|
||||
} else {
|
||||
setCurrentTab(e);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<Flex
|
||||
alignItems={'center'}
|
||||
cursor={'pointer'}
|
||||
py={2}
|
||||
px={3}
|
||||
borderRadius={'md'}
|
||||
_hover={{ bg: 'myGray.100' }}
|
||||
onClick={() => router.replace('/app/list')}
|
||||
>
|
||||
<IconButton
|
||||
mr={3}
|
||||
icon={<MyIcon name={'backFill'} w={'18px'} color={'myBlue.600'} />}
|
||||
bg={'white'}
|
||||
boxShadow={'1px 1px 9px rgba(0,0,0,0.15)'}
|
||||
h={'28px'}
|
||||
size={'sm'}
|
||||
borderRadius={'50%'}
|
||||
aria-label={''}
|
||||
/>
|
||||
我的应用
|
||||
</Flex>
|
||||
</Box>
|
||||
{/* phone tab */}
|
||||
<Box display={['block', 'none']} textAlign={'center'} py={3}>
|
||||
<Box className="textlg" fontSize={'xl'} fontWeight={'bold'}>
|
||||
{appDetail.name}
|
||||
</Box>
|
||||
</Flex>
|
||||
<SideTabs
|
||||
flex={1}
|
||||
mx={'auto'}
|
||||
mt={2}
|
||||
w={'100%'}
|
||||
list={tabList}
|
||||
activeId={currentTab}
|
||||
onChange={(e: any) => {
|
||||
if (e === 'startChat') {
|
||||
router.push(`/chat?appId=${appId}`);
|
||||
} else {
|
||||
setCurrentTab(e);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<Flex
|
||||
alignItems={'center'}
|
||||
cursor={'pointer'}
|
||||
py={2}
|
||||
px={3}
|
||||
borderRadius={'md'}
|
||||
_hover={{ bg: 'myGray.100' }}
|
||||
onClick={() => router.replace('/app/list')}
|
||||
>
|
||||
<IconButton
|
||||
mr={3}
|
||||
icon={<MyIcon name={'backFill'} w={'18px'} color={'myBlue.600'} />}
|
||||
bg={'white'}
|
||||
boxShadow={'1px 1px 9px rgba(0,0,0,0.15)'}
|
||||
h={'28px'}
|
||||
<Tabs
|
||||
mx={'auto'}
|
||||
mt={2}
|
||||
w={'100%'}
|
||||
list={tabList}
|
||||
size={'sm'}
|
||||
borderRadius={'50%'}
|
||||
aria-label={''}
|
||||
activeId={currentTab}
|
||||
onChange={(e: any) => {
|
||||
if (e === 'startChat') {
|
||||
router.push(`/chat?appId=${appId}`);
|
||||
} else {
|
||||
setCurrentTab(e);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
我的应用
|
||||
</Flex>
|
||||
</Box>
|
||||
{/* phone tab */}
|
||||
<Box display={['block', 'none']} textAlign={'center'} py={3}>
|
||||
<Box className="textlg" fontSize={'xl'} fontWeight={'bold'}>
|
||||
{appDetail.name}
|
||||
</Box>
|
||||
<Tabs
|
||||
mx={'auto'}
|
||||
mt={2}
|
||||
w={'100%'}
|
||||
list={tabList}
|
||||
size={'sm'}
|
||||
activeId={currentTab}
|
||||
onChange={(e: any) => {
|
||||
if (e === 'startChat') {
|
||||
router.push(`/chat?appId=${appId}`);
|
||||
} else {
|
||||
setCurrentTab(e);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
<Box flex={'1 0 0'} h={[0, '100%']} overflow={['overlay', '']}>
|
||||
{currentTab === TabEnum.simpleEdit && <SimpleEdit appId={appId} />}
|
||||
{currentTab === TabEnum.adEdit && appDetail && (
|
||||
<AdEdit app={appDetail} onClose={() => setCurrentTab(TabEnum.simpleEdit)} />
|
||||
)}
|
||||
{currentTab === TabEnum.logs && <Logs appId={appId} />}
|
||||
{currentTab === TabEnum.outLink && <OutLink appId={appId} />}
|
||||
</Box>
|
||||
</Flex>
|
||||
</PageContainer>
|
||||
<Box flex={'1 0 0'} h={[0, '100%']} overflow={['overlay', '']}>
|
||||
{currentTab === TabEnum.simpleEdit && <SimpleEdit appId={appId} />}
|
||||
{currentTab === TabEnum.adEdit && appDetail && (
|
||||
<AdEdit app={appDetail} onClose={() => setCurrentTab(TabEnum.simpleEdit)} />
|
||||
)}
|
||||
{currentTab === TabEnum.logs && <Logs appId={appId} />}
|
||||
{currentTab === TabEnum.outLink && <OutLink appId={appId} />}
|
||||
</Box>
|
||||
</Flex>
|
||||
</PageContainer>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
|
@@ -1,7 +1,7 @@
|
||||
import React, { useCallback, useRef } from 'react';
|
||||
import Head from 'next/head';
|
||||
import { useRouter } from 'next/router';
|
||||
import { getInitChatInfo, putChatHistory } from '@/web/core/chat/api';
|
||||
import { getInitChatInfo } from '@/web/core/chat/api';
|
||||
import {
|
||||
Box,
|
||||
Flex,
|
||||
|
@@ -116,7 +116,9 @@ const OutLink = ({
|
||||
updateHistory({
|
||||
...currentChat,
|
||||
updateTime: new Date(),
|
||||
title: newTitle
|
||||
title: newTitle,
|
||||
shareId,
|
||||
outLinkUid
|
||||
});
|
||||
}
|
||||
|
||||
@@ -148,7 +150,7 @@ const OutLink = ({
|
||||
|
||||
return { responseText, responseData, isNewChat: forbidRefresh.current };
|
||||
},
|
||||
[chatId, shareId, outLinkUid, setChatData, appId, updateHistory, router, histories]
|
||||
[chatId, shareId, outLinkUid, setChatData, appId, pushHistory, router, histories, updateHistory]
|
||||
);
|
||||
|
||||
const loadChatInfo = useCallback(
|
||||
@@ -309,13 +311,19 @@ const OutLink = ({
|
||||
});
|
||||
}}
|
||||
onSetHistoryTop={(e) => {
|
||||
updateHistory(e);
|
||||
updateHistory({
|
||||
...e,
|
||||
shareId,
|
||||
outLinkUid
|
||||
});
|
||||
}}
|
||||
onSetCustomTitle={async (e) => {
|
||||
updateHistory({
|
||||
chatId: e.chatId,
|
||||
title: e.title,
|
||||
customTitle: e.title
|
||||
customTitle: e.title,
|
||||
shareId,
|
||||
outLinkUid
|
||||
});
|
||||
}}
|
||||
/>
|
||||
@@ -349,7 +357,7 @@ const OutLink = ({
|
||||
feedbackType={'user'}
|
||||
onUpdateVariable={(e) => {}}
|
||||
onStartChat={startChat}
|
||||
onDelMessage={(e) => delOneHistoryItem({ ...e, chatId })}
|
||||
onDelMessage={(e) => delOneHistoryItem({ ...e, chatId, shareId, outLinkUid })}
|
||||
/>
|
||||
</Box>
|
||||
</Flex>
|
||||
|
@@ -173,7 +173,9 @@ const FileSelect = ({
|
||||
case 'pdf':
|
||||
return readPdfContent(file);
|
||||
case 'docx':
|
||||
return readDocContent(file);
|
||||
return readDocContent(file, {
|
||||
fileId
|
||||
});
|
||||
}
|
||||
return '';
|
||||
})();
|
||||
|
@@ -408,7 +408,7 @@ export function RawSourceText({
|
||||
await getFileAndOpen(sourceId as string);
|
||||
} catch (error) {
|
||||
toast({
|
||||
title: getErrText(error, '获取文件地址失败'),
|
||||
title: t(getErrText(error, 'error.fileNotFound')),
|
||||
status: 'error'
|
||||
});
|
||||
}
|
||||
|
@@ -9,7 +9,6 @@ import { oauthLogin } from '@/web/support/user/api';
|
||||
import { useToast } from '@/web/common/hooks/useToast';
|
||||
import Loading from '@/components/Loading';
|
||||
import { serviceSideProps } from '@/web/common/utils/i18n';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { getErrText } from '@fastgpt/global/common/error/utils';
|
||||
|
||||
const provider = ({ code, state }: { code: string; state: string }) => {
|
||||
|
Reference in New Issue
Block a user