4.6.8-alpha (#804)
* perf: redirect request and err log replace perf: dataset openapi feat: session fix: retry input error feat: 468 doc sub page feat: standard sub perf: rerank tip perf: rerank tip perf: api sdk perf: openapi sub plan perf: sub ui fix: ts * perf: init log * fix: variable select * sub page * icon * perf: llm model config * perf: menu ux * perf: system store * perf: publish app name * fix: init data * perf: flow edit ux * fix: value type format and ux * fix prompt editor default value (#13) * fix prompt editor default value * fix prompt editor update when not focus * add key with variable --------- Co-authored-by: Archer <545436317@qq.com> * fix: value type * doc * i18n * import path * home page * perf: mongo session running * fix: ts * perf: use toast * perf: flow edit * perf: sse response * slider ui * fetch error * fix prompt editor rerender when not focus by key defaultvalue (#14) * perf: prompt editor * feat: dataset search concat * perf: doc * fix:ts * perf: doc * fix json editor onblur value (#15) * faq * vector model default config * ipv6 --------- Co-authored-by: heheer <71265218+newfish-cmyk@users.noreply.github.com>
This commit is contained in:
@@ -8,7 +8,7 @@ import { theme } from '@/web/styles/theme';
|
||||
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
||||
import NProgress from 'nprogress'; //nprogress module
|
||||
import Router from 'next/router';
|
||||
import { clientInitData, feConfigs } from '@/web/common/system/staticData';
|
||||
import { clientInitData } from '@/web/common/system/staticData';
|
||||
import { appWithTranslation, useTranslation } from 'next-i18next';
|
||||
import { useRouter } from 'next/router';
|
||||
import { useSystemStore } from '@/web/common/system/useSystemStore';
|
||||
@@ -39,7 +39,7 @@ function App({ Component, pageProps }: AppProps) {
|
||||
const router = useRouter();
|
||||
const { hiId } = router.query as { hiId?: string };
|
||||
const { i18n } = useTranslation();
|
||||
const { loadGitStar } = useSystemStore();
|
||||
const { loadGitStar, setInitd, feConfigs } = useSystemStore();
|
||||
const [scripts, setScripts] = useState<FastGPTFeConfigsType['scripts']>([]);
|
||||
const [title, setTitle] = useState(process.env.SYSTEM_NAME || 'AI');
|
||||
|
||||
@@ -65,6 +65,7 @@ function App({ Component, pageProps }: AppProps) {
|
||||
}
|
||||
|
||||
setScripts(scripts || []);
|
||||
setInitd();
|
||||
})();
|
||||
|
||||
// add window error track
|
||||
|
||||
@@ -107,7 +107,7 @@ const BillDetail = ({ bill, onClose }: { bill: BillItemType; onClose: () => void
|
||||
</Flex>
|
||||
<Flex alignItems={'center'} pb={4}>
|
||||
<Box flex={'0 0 80px'}>{t('wallet.bill.Source')}:</Box>
|
||||
<Box>{BillSourceMap[bill.source]?.label}</Box>
|
||||
<Box>{t(BillSourceMap[bill.source]?.label)}</Box>
|
||||
</Flex>
|
||||
<Flex alignItems={'center'} pb={4}>
|
||||
<Box flex={'0 0 80px'}>{t('wallet.bill.Total')}:</Box>
|
||||
@@ -129,7 +129,7 @@ const BillDetail = ({ bill, onClose }: { bill: BillItemType; onClose: () => void
|
||||
{hasCharsLen && <Th>{t('wallet.bill.Text Length')}</Th>}
|
||||
{hasDuration && <Th>{t('wallet.bill.Duration')}</Th>}
|
||||
{hasDatasetSize && (
|
||||
<Th>{t('support.user.team.subscription.type.extraDatasetSize')}</Th>
|
||||
<Th>{t('support.wallet.subscription.type.extraDatasetSize')}</Th>
|
||||
)}
|
||||
<Th>费用(¥)</Th>
|
||||
</Tr>
|
||||
|
||||
@@ -45,7 +45,10 @@ const BillTable = () => {
|
||||
const sourceList = useMemo(
|
||||
() => [
|
||||
{ label: t('common.All'), value: '' },
|
||||
...Object.entries(BillSourceMap).map(([key, value]) => ({ label: value.label, value: key }))
|
||||
...Object.entries(BillSourceMap).map(([key, value]) => ({
|
||||
label: t(value.label),
|
||||
value: key
|
||||
}))
|
||||
],
|
||||
[t]
|
||||
);
|
||||
@@ -152,7 +155,7 @@ const BillTable = () => {
|
||||
<Tr key={item.id}>
|
||||
{/* <Td>{item.memberName}</Td> */}
|
||||
<Td>{dayjs(item.time).format('YYYY/MM/DD HH:mm:ss')}</Td>
|
||||
<Td>{BillSourceMap[item.source]?.label}</Td>
|
||||
<Td>{t(BillSourceMap[item.source]?.label)}</Td>
|
||||
<Td>{t(item.appName) || '-'}</Td>
|
||||
<Td>{item.total}元</Td>
|
||||
<Td>
|
||||
|
||||
@@ -13,14 +13,14 @@ import {
|
||||
} from '@chakra-ui/react';
|
||||
import { useForm } from 'react-hook-form';
|
||||
import { UserUpdateParams } from '@/types/user';
|
||||
import { useToast } from '@/web/common/hooks/useToast';
|
||||
import { useToast } from '@fastgpt/web/hooks/useToast';
|
||||
import { useUserStore } from '@/web/support/user/useUserStore';
|
||||
import type { UserType } from '@fastgpt/global/support/user/type.d';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import dynamic from 'next/dynamic';
|
||||
import { useSelectFile } from '@/web/common/file/hooks/useSelectFile';
|
||||
import { compressImgFileAndUpload } from '@/web/common/file/controller';
|
||||
import { feConfigs, systemVersion } from '@/web/common/system/staticData';
|
||||
import { useSystemStore } from '@/web/common/system/useSystemStore';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import { timezoneList } from '@fastgpt/global/common/time/timezone';
|
||||
import Avatar from '@/components/Avatar';
|
||||
@@ -44,6 +44,7 @@ const SubDatasetModal = dynamic(() => import('@/components/support/wallet/SubDat
|
||||
const UserInfo = () => {
|
||||
const theme = useTheme();
|
||||
const router = useRouter();
|
||||
const { feConfigs, systemVersion } = useSystemStore();
|
||||
const { t, i18n } = useTranslation();
|
||||
const { userInfo, updateUserInfo, initUserInfo } = useUserStore();
|
||||
const timezones = useRef(timezoneList());
|
||||
@@ -122,12 +123,11 @@ const UserInfo = () => {
|
||||
}
|
||||
});
|
||||
|
||||
const { data: datasetSub = { maxSize: 0, usedSize: 0 } } = useQuery(
|
||||
['getTeamDatasetValidSub'],
|
||||
getTeamDatasetValidSub
|
||||
);
|
||||
const {
|
||||
data: teamSubPlan = { totalPoints: 0, usedPoints: 0, datasetMaxSize: 800, usedDatasetSize: 0 }
|
||||
} = useQuery(['getTeamDatasetValidSub'], getTeamDatasetValidSub);
|
||||
const datasetUsageMap = useMemo(() => {
|
||||
const rate = datasetSub.usedSize / datasetSub.maxSize;
|
||||
const rate = teamSubPlan.usedDatasetSize / teamSubPlan.datasetMaxSize;
|
||||
|
||||
const colorScheme = (() => {
|
||||
if (rate < 0.5) return 'green';
|
||||
@@ -138,10 +138,10 @@ const UserInfo = () => {
|
||||
return {
|
||||
colorScheme,
|
||||
value: rate * 100,
|
||||
maxSize: datasetSub.maxSize,
|
||||
usedSize: datasetSub.usedSize
|
||||
maxSize: teamSubPlan.datasetMaxSize || t('common.Unlimited'),
|
||||
usedSize: teamSubPlan.usedDatasetSize
|
||||
};
|
||||
}, [datasetSub.maxSize, datasetSub.usedSize]);
|
||||
}, [teamSubPlan.usedDatasetSize, teamSubPlan.datasetMaxSize, t]);
|
||||
|
||||
return (
|
||||
<Box
|
||||
@@ -276,7 +276,7 @@ const UserInfo = () => {
|
||||
<Flex alignItems={'center'}>
|
||||
<Box flex={'1 0 0'} fontSize={'md'}>
|
||||
{t('support.user.team.Dataset usage')}: {datasetUsageMap.usedSize}/
|
||||
{datasetSub.maxSize}
|
||||
{datasetUsageMap.maxSize}
|
||||
</Box>
|
||||
{userInfo?.team?.canWrite && (
|
||||
<Button size={'sm'} onClick={onOpenSubDatasetModal}>
|
||||
@@ -316,7 +316,7 @@ const UserInfo = () => {
|
||||
userSelect={'none'}
|
||||
textDecoration={'none !important'}
|
||||
>
|
||||
<MyIcon name={'common/courseLight'} w={'18px'} />
|
||||
<MyIcon name={'common/courseLight'} w={'18px'} color={'myGray.600'} />
|
||||
<Box ml={2} flex={1}>
|
||||
{t('system.Help Document')}
|
||||
</Box>
|
||||
@@ -366,7 +366,7 @@ const UserInfo = () => {
|
||||
userSelect={'none'}
|
||||
onClick={onOpenOpenai}
|
||||
>
|
||||
<Avatar src={'/imgs/openai.png'} w={'18px'} />
|
||||
<MyIcon name={'common/openai'} w={'18px'} color={'myGray.600'} />
|
||||
<Box ml={2} flex={1}>
|
||||
OpenAI/OneAPI 账号
|
||||
</Box>
|
||||
|
||||
@@ -32,7 +32,7 @@ const OpenAIAccountModal = ({
|
||||
<MyModal
|
||||
isOpen
|
||||
onClose={onClose}
|
||||
iconSrc="/imgs/modal/openai.svg"
|
||||
iconSrc="common/openai"
|
||||
title={t('user.OpenAI Account Setting')}
|
||||
>
|
||||
<ModalBody>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React, { useState, useCallback } from 'react';
|
||||
import { ModalFooter, ModalBody, Button, Input, Box, Grid } from '@chakra-ui/react';
|
||||
import { getPayCode, checkPayResult } from '@/web/support/wallet/pay/api';
|
||||
import { useToast } from '@/web/common/hooks/useToast';
|
||||
import { useToast } from '@fastgpt/web/hooks/useToast';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { useRouter } from 'next/router';
|
||||
import { getErrText } from '@fastgpt/global/common/error/utils';
|
||||
|
||||
@@ -16,7 +16,7 @@ import type { PaySchema } from '@fastgpt/global/support/wallet/pay/type.d';
|
||||
import dayjs from 'dayjs';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { formatStorePrice2Read } from '@fastgpt/global/support/wallet/bill/tools';
|
||||
import { useToast } from '@/web/common/hooks/useToast';
|
||||
import { useToast } from '@fastgpt/web/hooks/useToast';
|
||||
import { useLoading } from '@/web/common/hooks/useLoading';
|
||||
import MyIcon from '@fastgpt/web/components/common/Icon';
|
||||
|
||||
|
||||
@@ -10,7 +10,6 @@ import SideTabs from '@/components/SideTabs';
|
||||
import Tabs from '@/components/Tabs';
|
||||
import UserInfo from './components/Info';
|
||||
import { serviceSideProps } from '@/web/common/utils/i18n';
|
||||
import { feConfigs } from '@/web/common/system/staticData';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import Script from 'next/script';
|
||||
|
||||
@@ -35,6 +34,7 @@ enum TabEnum {
|
||||
const Account = ({ currentTab }: { currentTab: `${TabEnum}` }) => {
|
||||
const { t } = useTranslation();
|
||||
const { userInfo, setUserInfo } = useUserStore();
|
||||
const { feConfigs, isPc } = useSystemStore();
|
||||
|
||||
const tabList = [
|
||||
{
|
||||
@@ -116,7 +116,6 @@ const Account = ({ currentTab }: { currentTab: `${TabEnum}` }) => {
|
||||
|
||||
const router = useRouter();
|
||||
const theme = useTheme();
|
||||
const { isPc } = useSystemStore();
|
||||
|
||||
const setCurrentTab = useCallback(
|
||||
(tab: string) => {
|
||||
|
||||
@@ -22,10 +22,8 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
|
||||
jsonRes<InitDateResponse>(res, {
|
||||
data: {
|
||||
feConfigs: global.feConfigs,
|
||||
chatModels: global.chatModels,
|
||||
qaModels: global.qaModels,
|
||||
cqModels: global.cqModels,
|
||||
extractModels: global.extractModels,
|
||||
subPlans: global.subPlans,
|
||||
llmModels: global.llmModels,
|
||||
vectorModels: global.vectorModels,
|
||||
reRankModels:
|
||||
global.reRankModels?.map((item) => ({
|
||||
@@ -33,7 +31,6 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
|
||||
requestUrl: undefined,
|
||||
requestAuth: undefined
|
||||
})) || [],
|
||||
qgModes: global.qgModels,
|
||||
whisperModel: global.whisperModel,
|
||||
audioSpeechModels: global.audioSpeechModels,
|
||||
systemVersion: global.systemVersion || '0.0.0',
|
||||
@@ -119,11 +116,8 @@ export async function initSystemConfig() {
|
||||
...fileRes.systemEnv,
|
||||
...(dbConfig.systemEnv || {})
|
||||
},
|
||||
chatModels: dbConfig.chatModels || fileRes.chatModels || [],
|
||||
qaModels: dbConfig.qaModels || fileRes.qaModels || [],
|
||||
cqModels: dbConfig.cqModels || fileRes.cqModels || [],
|
||||
extractModels: dbConfig.extractModels || fileRes.extractModels || [],
|
||||
qgModels: dbConfig.qgModels || fileRes.qgModels || [],
|
||||
subPlans: dbConfig.subPlans || fileRes.subPlans,
|
||||
llmModels: dbConfig.llmModels || fileRes.llmModels || [],
|
||||
vectorModels: dbConfig.vectorModels || fileRes.vectorModels || [],
|
||||
reRankModels: dbConfig.reRankModels || fileRes.reRankModels || [],
|
||||
audioSpeechModels: dbConfig.audioSpeechModels || fileRes.audioSpeechModels || [],
|
||||
@@ -133,12 +127,9 @@ export async function initSystemConfig() {
|
||||
// set config
|
||||
global.feConfigs = config.feConfigs;
|
||||
global.systemEnv = config.systemEnv;
|
||||
global.subPlans = config.subPlans;
|
||||
|
||||
global.chatModels = config.chatModels;
|
||||
global.qaModels = config.qaModels;
|
||||
global.cqModels = config.cqModels;
|
||||
global.extractModels = config.extractModels;
|
||||
global.qgModels = config.qgModels;
|
||||
global.llmModels = config.llmModels;
|
||||
global.vectorModels = config.vectorModels;
|
||||
global.reRankModels = config.reRankModels;
|
||||
global.audioSpeechModels = config.audioSpeechModels;
|
||||
@@ -147,11 +138,8 @@ export async function initSystemConfig() {
|
||||
console.log({
|
||||
feConfigs: global.feConfigs,
|
||||
systemEnv: global.systemEnv,
|
||||
chatModels: global.chatModels,
|
||||
qaModels: global.qaModels,
|
||||
cqModels: global.cqModels,
|
||||
extractModels: global.extractModels,
|
||||
qgModels: global.qgModels,
|
||||
subPlans: global.subPlans,
|
||||
llmModels: global.llmModels,
|
||||
vectorModels: global.vectorModels,
|
||||
reRankModels: global.reRankModels,
|
||||
audioSpeechModels: global.audioSpeechModels,
|
||||
|
||||
@@ -17,7 +17,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
|
||||
shareId
|
||||
});
|
||||
|
||||
const qgModel = global.qgModels[0];
|
||||
const qgModel = global.llmModels[0];
|
||||
|
||||
const { result, inputTokens, outputTokens } = await createQuestionGuide({
|
||||
messages,
|
||||
|
||||
@@ -6,6 +6,7 @@ import { MongoApp } from '@fastgpt/service/core/app/schema';
|
||||
import { MongoOutLink } from '@fastgpt/service/support/outLink/schema';
|
||||
import { authApp } from '@fastgpt/service/support/permission/auth/app';
|
||||
import { MongoChatItem } from '@fastgpt/service/core/chat/chatItemSchema';
|
||||
import { mongoSessionRun } from '@fastgpt/service/common/mongo/sessionRun';
|
||||
|
||||
/* 获取我的模型 */
|
||||
export default async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
|
||||
@@ -21,21 +22,33 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
|
||||
await authApp({ req, authToken: true, appId, per: 'owner' });
|
||||
|
||||
// 删除对应的聊天
|
||||
await MongoChatItem.deleteMany({
|
||||
appId
|
||||
});
|
||||
await MongoChat.deleteMany({
|
||||
appId
|
||||
});
|
||||
|
||||
// 删除分享链接
|
||||
await MongoOutLink.deleteMany({
|
||||
appId
|
||||
});
|
||||
|
||||
// 删除模型
|
||||
await MongoApp.deleteOne({
|
||||
_id: appId
|
||||
await mongoSessionRun(async (session) => {
|
||||
await MongoChatItem.deleteMany(
|
||||
{
|
||||
appId
|
||||
},
|
||||
{ session }
|
||||
);
|
||||
await MongoChat.deleteMany(
|
||||
{
|
||||
appId
|
||||
},
|
||||
{ session }
|
||||
);
|
||||
// 删除分享链接
|
||||
await MongoOutLink.deleteMany(
|
||||
{
|
||||
appId
|
||||
},
|
||||
{ session }
|
||||
);
|
||||
// delete app
|
||||
await MongoApp.deleteOne(
|
||||
{
|
||||
_id: appId
|
||||
},
|
||||
{ session }
|
||||
);
|
||||
});
|
||||
|
||||
jsonRes(res);
|
||||
|
||||
@@ -8,11 +8,11 @@ import type { AppSimpleEditFormType } from '@fastgpt/global/core/app/type.d';
|
||||
import type { ModuleItemType } from '@fastgpt/global/core/module/type';
|
||||
import { FormatForm2ModulesProps } from '@fastgpt/global/core/app/api';
|
||||
import { DatasetSearchModeEnum } from '@fastgpt/global/core/dataset/constants';
|
||||
import { getExtractModel } from '@/service/core/ai/model';
|
||||
import { getLLMModel } from '@/service/core/ai/model';
|
||||
|
||||
export default async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
|
||||
try {
|
||||
const { formData, chatModelMaxToken, chatModelList } = req.body as FormatForm2ModulesProps;
|
||||
const { formData, chatModelMaxToken } = req.body as FormatForm2ModulesProps;
|
||||
|
||||
const modules = [
|
||||
...(formData.dataset.datasets.length > 0
|
||||
@@ -381,7 +381,7 @@ function datasetTemplate({ formData, maxToken }: Props): ModuleItemType[] {
|
||||
key: 'usingReRank',
|
||||
type: 'hidden',
|
||||
label: '',
|
||||
valueType: 'string',
|
||||
valueType: 'boolean',
|
||||
showTargetInApp: false,
|
||||
showTargetInPlugin: false,
|
||||
value: true,
|
||||
@@ -676,7 +676,7 @@ function datasetTemplate({ formData, maxToken }: Props): ModuleItemType[] {
|
||||
label: 'core.module.input.label.aiModel',
|
||||
required: true,
|
||||
valueType: 'string',
|
||||
value: getExtractModel().model,
|
||||
value: getLLMModel().model,
|
||||
showTargetInApp: false,
|
||||
showTargetInPlugin: false,
|
||||
connected: false
|
||||
|
||||
@@ -7,7 +7,7 @@ import { jsonRes } from '@fastgpt/service/common/response';
|
||||
import type { AppSimpleEditFormType } from '@fastgpt/global/core/app/type.d';
|
||||
import type { ModuleItemType } from '@fastgpt/global/core/module/type';
|
||||
import { FormatForm2ModulesProps } from '@fastgpt/global/core/app/api';
|
||||
import { getExtractModel } from '@/service/core/ai/model';
|
||||
import { getLLMModel } from '@/service/core/ai/model';
|
||||
|
||||
export default async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
|
||||
try {
|
||||
@@ -377,7 +377,7 @@ function datasetTemplate(formData: AppSimpleEditFormType): ModuleItemType[] {
|
||||
key: 'usingReRank',
|
||||
type: 'hidden',
|
||||
label: '',
|
||||
valueType: 'string',
|
||||
valueType: 'boolean',
|
||||
showTargetInApp: false,
|
||||
showTargetInPlugin: false,
|
||||
value: formData.dataset.usingReRank,
|
||||
@@ -686,7 +686,7 @@ function datasetTemplate(formData: AppSimpleEditFormType): ModuleItemType[] {
|
||||
label: 'core.module.input.label.aiModel',
|
||||
required: true,
|
||||
valueType: 'string',
|
||||
value: getExtractModel().model,
|
||||
value: getLLMModel().model,
|
||||
showTargetInApp: false,
|
||||
showTargetInPlugin: false,
|
||||
connected: false
|
||||
|
||||
@@ -6,7 +6,7 @@ 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';
|
||||
import { getLLMModel } from '@/service/core/ai/model';
|
||||
|
||||
/* 获取我的模型 */
|
||||
export default async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
|
||||
@@ -32,7 +32,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
|
||||
if (item.flowType === FlowNodeTypeEnum.chatNode) {
|
||||
const model =
|
||||
item.inputs.find((item) => item.key === ModuleInputKeyEnum.aiModel)?.value || '';
|
||||
const chatModel = getChatModel(model);
|
||||
const chatModel = getLLMModel(model);
|
||||
const quoteMaxToken = chatModel.quoteMaxToken || 3000;
|
||||
|
||||
maxTokens = Math.max(maxTokens, quoteMaxToken);
|
||||
@@ -42,7 +42,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
|
||||
modules.forEach((item) => {
|
||||
if (item.flowType === FlowNodeTypeEnum.datasetSearchNode) {
|
||||
item.inputs.forEach((input) => {
|
||||
if (input.key === ModuleInputKeyEnum.datasetLimit) {
|
||||
if (input.key === ModuleInputKeyEnum.datasetMaxTokens) {
|
||||
const val = input.value as number;
|
||||
if (val > maxTokens) {
|
||||
input.value = maxTokens;
|
||||
|
||||
@@ -5,6 +5,7 @@ import { MongoChat } from '@fastgpt/service/core/chat/chatSchema';
|
||||
import { MongoChatItem } from '@fastgpt/service/core/chat/chatItemSchema';
|
||||
import { DelHistoryProps } from '@/global/core/chat/api';
|
||||
import { autChatCrud } from '@/service/support/permission/auth/chat';
|
||||
import { mongoSessionRun } from '@fastgpt/service/common/mongo/sessionRun';
|
||||
|
||||
/* clear chat history */
|
||||
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
@@ -22,13 +23,21 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
|
||||
per: 'w'
|
||||
});
|
||||
|
||||
await MongoChatItem.deleteMany({
|
||||
appId,
|
||||
chatId
|
||||
});
|
||||
await MongoChat.findOneAndRemove({
|
||||
appId,
|
||||
chatId
|
||||
await mongoSessionRun(async (session) => {
|
||||
await MongoChatItem.deleteMany(
|
||||
{
|
||||
appId,
|
||||
chatId
|
||||
},
|
||||
{ session }
|
||||
);
|
||||
await MongoChat.findOneAndRemove(
|
||||
{
|
||||
appId,
|
||||
chatId
|
||||
},
|
||||
{ session }
|
||||
);
|
||||
});
|
||||
|
||||
jsonRes(res);
|
||||
|
||||
@@ -21,12 +21,14 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
|
||||
per: 'w'
|
||||
});
|
||||
|
||||
const { _id } = await createOneCollection({
|
||||
...body,
|
||||
teamId,
|
||||
tmbId
|
||||
});
|
||||
|
||||
jsonRes(res, {
|
||||
data: await createOneCollection({
|
||||
...body,
|
||||
teamId,
|
||||
tmbId
|
||||
})
|
||||
data: _id
|
||||
});
|
||||
} catch (err) {
|
||||
jsonRes(res, {
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
import type { NextApiRequest, NextApiResponse } from 'next';
|
||||
import { jsonRes } from '@fastgpt/service/common/response';
|
||||
import { connectToDatabase } from '@/service/mongo';
|
||||
import { uploadFile } from '@fastgpt/service/common/file/gridfs/controller';
|
||||
import { delFileByFileIdList, uploadFile } from '@fastgpt/service/common/file/gridfs/controller';
|
||||
import { getUploadModel } from '@fastgpt/service/common/file/multer';
|
||||
import { authDataset } from '@fastgpt/service/support/permission/auth/dataset';
|
||||
import { FileCreateDatasetCollectionParams } from '@fastgpt/global/core/dataset/api';
|
||||
import { removeFilesByPaths } from '@fastgpt/service/common/file/utils';
|
||||
import { createOneCollection } from '@fastgpt/service/core/dataset/collection/controller';
|
||||
import { DatasetCollectionTypeEnum } from '@fastgpt/global/core/dataset/constants';
|
||||
import { BucketNameEnum } from '@fastgpt/global/common/file/constants';
|
||||
|
||||
/**
|
||||
* Creates the multer uploader
|
||||
@@ -18,7 +19,7 @@ const upload = getUploadModel({
|
||||
|
||||
export default async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
|
||||
let filePaths: string[] = [];
|
||||
|
||||
let fileId: string = '';
|
||||
const { datasetId } = req.query as { datasetId: string };
|
||||
|
||||
try {
|
||||
@@ -45,7 +46,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
|
||||
const { fileMetadata, collectionMetadata, ...collectionData } = data;
|
||||
|
||||
// upload file and create collection
|
||||
const fileId = await uploadFile({
|
||||
fileId = await uploadFile({
|
||||
teamId,
|
||||
tmbId,
|
||||
bucketName,
|
||||
@@ -56,7 +57,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
|
||||
});
|
||||
|
||||
// create collection
|
||||
const collectionId = await createOneCollection({
|
||||
const { _id: collectionId } = await createOneCollection({
|
||||
...collectionData,
|
||||
metadata: collectionMetadata,
|
||||
teamId,
|
||||
@@ -69,6 +70,14 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
|
||||
data: collectionId
|
||||
});
|
||||
} catch (error) {
|
||||
if (fileId) {
|
||||
try {
|
||||
await delFileByFileIdList({
|
||||
fileIdList: [fileId],
|
||||
bucketName: BucketNameEnum.dataset
|
||||
});
|
||||
} catch (error) {}
|
||||
}
|
||||
jsonRes(res, {
|
||||
code: 500,
|
||||
error
|
||||
|
||||
@@ -15,8 +15,10 @@ import { checkDatasetLimit } from '@fastgpt/service/support/permission/limit/dat
|
||||
import { predictDataLimitLength } from '@fastgpt/global/core/dataset/utils';
|
||||
import { createTrainingBill } from '@fastgpt/service/support/wallet/bill/controller';
|
||||
import { BillSourceEnum } from '@fastgpt/global/support/wallet/bill/constants';
|
||||
import { getQAModel, getVectorModel } from '@/service/core/ai/model';
|
||||
import { getLLMModel, getVectorModel } from '@/service/core/ai/model';
|
||||
import { reloadCollectionChunks } from '@fastgpt/service/core/dataset/collection/utils';
|
||||
import { getStandardSubPlan } from '@/service/support/wallet/sub/utils';
|
||||
import { mongoSessionRun } from '@fastgpt/service/common/mongo/sessionRun';
|
||||
|
||||
export default async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
|
||||
try {
|
||||
@@ -41,39 +43,51 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
|
||||
// 1. check dataset limit
|
||||
await checkDatasetLimit({
|
||||
teamId,
|
||||
freeSize: global.feConfigs?.subscription?.datasetStoreFreeSize,
|
||||
insertLen: predictDataLimitLength(trainingType, new Array(10))
|
||||
insertLen: predictDataLimitLength(trainingType, new Array(10)),
|
||||
standardPlans: getStandardSubPlan()
|
||||
});
|
||||
|
||||
// 2. create collection
|
||||
const collectionId = await createOneCollection({
|
||||
...body,
|
||||
name: link,
|
||||
teamId,
|
||||
tmbId,
|
||||
type: DatasetCollectionTypeEnum.link,
|
||||
const { _id: collectionId } = await mongoSessionRun(async (session) => {
|
||||
// 2. create collection
|
||||
const collection = await createOneCollection({
|
||||
...body,
|
||||
name: link,
|
||||
teamId,
|
||||
tmbId,
|
||||
type: DatasetCollectionTypeEnum.link,
|
||||
|
||||
trainingType,
|
||||
chunkSize,
|
||||
chunkSplitter,
|
||||
qaPrompt,
|
||||
trainingType,
|
||||
chunkSize,
|
||||
chunkSplitter,
|
||||
qaPrompt,
|
||||
|
||||
rawLink: link
|
||||
});
|
||||
rawLink: link,
|
||||
session
|
||||
});
|
||||
|
||||
// 3. create bill and start sync
|
||||
const { billId } = await createTrainingBill({
|
||||
teamId,
|
||||
tmbId,
|
||||
appName: 'core.dataset.collection.Sync Collection',
|
||||
billSource: BillSourceEnum.training,
|
||||
vectorModel: getVectorModel(dataset.vectorModel).name,
|
||||
agentModel: getQAModel(dataset.agentModel).name
|
||||
});
|
||||
await reloadCollectionChunks({
|
||||
collectionId,
|
||||
tmbId,
|
||||
billId
|
||||
// 3. create bill and start sync
|
||||
const { billId } = await createTrainingBill({
|
||||
teamId,
|
||||
tmbId,
|
||||
appName: 'core.dataset.collection.Sync Collection',
|
||||
billSource: BillSourceEnum.training,
|
||||
vectorModel: getVectorModel(dataset.vectorModel).name,
|
||||
agentModel: getLLMModel(dataset.agentModel).name,
|
||||
session
|
||||
});
|
||||
|
||||
// load
|
||||
await reloadCollectionChunks({
|
||||
collection: {
|
||||
...collection.toObject(),
|
||||
datasetId: dataset
|
||||
},
|
||||
tmbId,
|
||||
billId,
|
||||
session
|
||||
});
|
||||
|
||||
return collection;
|
||||
});
|
||||
|
||||
jsonRes(res, {
|
||||
|
||||
@@ -18,7 +18,8 @@ import { pushDataToTrainingQueue } from '@/service/core/dataset/data/controller'
|
||||
import { hashStr } from '@fastgpt/global/common/string/tools';
|
||||
import { createTrainingBill } from '@fastgpt/service/support/wallet/bill/controller';
|
||||
import { BillSourceEnum } from '@fastgpt/global/support/wallet/bill/constants';
|
||||
import { getQAModel, getVectorModel } from '@/service/core/ai/model';
|
||||
import { getLLMModel, getVectorModel } from '@/service/core/ai/model';
|
||||
import { getStandardSubPlan } from '@/service/support/wallet/sub/utils';
|
||||
|
||||
export default async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
|
||||
try {
|
||||
@@ -52,12 +53,12 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
|
||||
// 2. check dataset limit
|
||||
await checkDatasetLimit({
|
||||
teamId,
|
||||
freeSize: global.feConfigs?.subscription?.datasetStoreFreeSize,
|
||||
insertLen: predictDataLimitLength(trainingType, chunks)
|
||||
insertLen: predictDataLimitLength(trainingType, chunks),
|
||||
standardPlans: getStandardSubPlan()
|
||||
});
|
||||
|
||||
// 3. create collection and training bill
|
||||
const [collectionId, { billId }] = await Promise.all([
|
||||
const [{ _id: collectionId }, { billId }] = await Promise.all([
|
||||
createOneCollection({
|
||||
...body,
|
||||
teamId,
|
||||
@@ -79,7 +80,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
|
||||
appName: name,
|
||||
billSource: BillSourceEnum.training,
|
||||
vectorModel: getVectorModel(dataset.vectorModel)?.name,
|
||||
agentModel: getQAModel(dataset.agentModel)?.name
|
||||
agentModel: getLLMModel(dataset.agentModel)?.name
|
||||
})
|
||||
]);
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import { connectToDatabase } from '@/service/mongo';
|
||||
import { findCollectionAndChild } from '@fastgpt/service/core/dataset/collection/utils';
|
||||
import { delCollectionAndRelatedSources } from '@fastgpt/service/core/dataset/collection/controller';
|
||||
import { authDatasetCollection } from '@fastgpt/service/support/permission/auth/dataset';
|
||||
import { mongoSessionRun } from '@fastgpt/service/common/mongo/sessionRun';
|
||||
|
||||
export default async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
|
||||
try {
|
||||
@@ -32,9 +33,12 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
|
||||
});
|
||||
|
||||
// delete
|
||||
await delCollectionAndRelatedSources({
|
||||
collections
|
||||
});
|
||||
await mongoSessionRun((session) =>
|
||||
delCollectionAndRelatedSources({
|
||||
collections,
|
||||
session
|
||||
})
|
||||
);
|
||||
|
||||
jsonRes(res);
|
||||
} catch (err) {
|
||||
|
||||
@@ -14,8 +14,9 @@ import {
|
||||
import { DatasetErrEnum } from '@fastgpt/global/common/error/code/dataset';
|
||||
import { createTrainingBill } from '@fastgpt/service/support/wallet/bill/controller';
|
||||
import { BillSourceEnum } from '@fastgpt/global/support/wallet/bill/constants';
|
||||
import { getQAModel, getVectorModel } from '@/service/core/ai/model';
|
||||
import { getLLMModel, getVectorModel } from '@/service/core/ai/model';
|
||||
import { createOneCollection } from '@fastgpt/service/core/dataset/collection/controller';
|
||||
import { mongoSessionRun } from '@fastgpt/service/common/mongo/sessionRun';
|
||||
|
||||
export default async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
|
||||
try {
|
||||
@@ -27,7 +28,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
|
||||
throw new Error('CollectionIdId is required');
|
||||
}
|
||||
|
||||
const { collection, teamId, tmbId } = await authDatasetCollection({
|
||||
const { collection, tmbId } = await authDatasetCollection({
|
||||
req,
|
||||
authToken: true,
|
||||
collectionId,
|
||||
@@ -51,44 +52,54 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
|
||||
/* Not the same original text, create and reload */
|
||||
|
||||
const vectorModelData = getVectorModel(collection.datasetId.vectorModel);
|
||||
const agentModelData = getQAModel(collection.datasetId.agentModel);
|
||||
// create training bill
|
||||
const { billId } = await createTrainingBill({
|
||||
teamId: collection.teamId,
|
||||
tmbId,
|
||||
appName: 'core.dataset.collection.Sync Collection',
|
||||
billSource: BillSourceEnum.training,
|
||||
vectorModel: vectorModelData.name,
|
||||
agentModel: agentModelData.name
|
||||
});
|
||||
const agentModelData = getLLMModel(collection.datasetId.agentModel);
|
||||
|
||||
// create a collection and delete old
|
||||
const _id = await createOneCollection({
|
||||
teamId: collection.teamId,
|
||||
tmbId: collection.tmbId,
|
||||
parentId: collection.parentId,
|
||||
datasetId: collection.datasetId._id,
|
||||
name: title || collection.name,
|
||||
type: collection.type,
|
||||
trainingType: collection.trainingType,
|
||||
chunkSize: collection.chunkSize,
|
||||
fileId: collection.fileId,
|
||||
rawLink: collection.rawLink,
|
||||
metadata: collection.metadata,
|
||||
createTime: collection.createTime
|
||||
});
|
||||
await mongoSessionRun(async (session) => {
|
||||
// create training bill
|
||||
const { billId } = await createTrainingBill({
|
||||
teamId: collection.teamId,
|
||||
tmbId,
|
||||
appName: 'core.dataset.collection.Sync Collection',
|
||||
billSource: BillSourceEnum.training,
|
||||
vectorModel: vectorModelData.name,
|
||||
agentModel: agentModelData.name,
|
||||
session
|
||||
});
|
||||
|
||||
// start load
|
||||
await reloadCollectionChunks({
|
||||
collectionId: _id,
|
||||
tmbId,
|
||||
billId,
|
||||
rawText
|
||||
});
|
||||
// create a collection and delete old
|
||||
const newCol = await createOneCollection({
|
||||
teamId: collection.teamId,
|
||||
tmbId: collection.tmbId,
|
||||
parentId: collection.parentId,
|
||||
datasetId: collection.datasetId._id,
|
||||
name: title || collection.name,
|
||||
type: collection.type,
|
||||
trainingType: collection.trainingType,
|
||||
chunkSize: collection.chunkSize,
|
||||
fileId: collection.fileId,
|
||||
rawLink: collection.rawLink,
|
||||
metadata: collection.metadata,
|
||||
createTime: collection.createTime,
|
||||
session
|
||||
});
|
||||
|
||||
// delete old collection
|
||||
await delCollectionAndRelatedSources({
|
||||
collections: [collection]
|
||||
// start load
|
||||
await reloadCollectionChunks({
|
||||
collection: {
|
||||
...newCol.toObject(),
|
||||
datasetId: collection.datasetId
|
||||
},
|
||||
tmbId,
|
||||
billId,
|
||||
rawText,
|
||||
session
|
||||
});
|
||||
|
||||
// delete old collection
|
||||
await delCollectionAndRelatedSources({
|
||||
collections: [collection],
|
||||
session
|
||||
});
|
||||
});
|
||||
|
||||
jsonRes(res, {
|
||||
|
||||
@@ -6,7 +6,7 @@ import type { CreateDatasetParams } from '@/global/core/dataset/api.d';
|
||||
import { createDefaultCollection } from '@fastgpt/service/core/dataset/collection/controller';
|
||||
import { authUserNotVisitor } from '@fastgpt/service/support/permission/auth/user';
|
||||
import { DatasetTypeEnum } from '@fastgpt/global/core/dataset/constants';
|
||||
import { getQAModel, getVectorModel } from '@/service/core/ai/model';
|
||||
import { getLLMModel, getVectorModel, getDatasetModel } from '@/service/core/ai/model';
|
||||
|
||||
export default async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
|
||||
try {
|
||||
@@ -17,7 +17,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
|
||||
type = DatasetTypeEnum.dataset,
|
||||
avatar,
|
||||
vectorModel = global.vectorModels[0].model,
|
||||
agentModel = global.qaModels[0].model
|
||||
agentModel = getDatasetModel().model
|
||||
} = req.body as CreateDatasetParams;
|
||||
|
||||
// auth
|
||||
@@ -25,7 +25,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
|
||||
|
||||
// check model valid
|
||||
const vectorModelStore = getVectorModel(vectorModel);
|
||||
const agentModelStore = getQAModel(agentModel);
|
||||
const agentModelStore = getLLMModel(agentModel);
|
||||
if (!vectorModelStore || !agentModelStore) {
|
||||
throw new Error('vectorModel or qaModel is invalid');
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ import { pushGenerateVectorBill } from '@/service/support/wallet/bill/push';
|
||||
import { InsertOneDatasetDataProps } from '@/global/core/dataset/api';
|
||||
import { simpleText } from '@fastgpt/global/common/string/tools';
|
||||
import { checkDatasetLimit } from '@fastgpt/service/support/permission/limit/dataset';
|
||||
import { getStandardSubPlan } from '@/service/support/wallet/sub/utils';
|
||||
|
||||
export default withNextCors(async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
|
||||
try {
|
||||
@@ -42,8 +43,8 @@ export default withNextCors(async function handler(req: NextApiRequest, res: Nex
|
||||
|
||||
await checkDatasetLimit({
|
||||
teamId,
|
||||
freeSize: global.feConfigs?.subscription?.datasetStoreFreeSize,
|
||||
insertLen: 1
|
||||
insertLen: 1,
|
||||
standardPlans: getStandardSubPlan()
|
||||
});
|
||||
|
||||
// auth collection and get dataset
|
||||
|
||||
@@ -11,6 +11,7 @@ import { authDatasetCollection } from '@fastgpt/service/support/permission/auth/
|
||||
import { checkDatasetLimit } from '@fastgpt/service/support/permission/limit/dataset';
|
||||
import { predictDataLimitLength } from '@fastgpt/global/core/dataset/utils';
|
||||
import { pushDataToTrainingQueue } from '@/service/core/dataset/data/controller';
|
||||
import { getStandardSubPlan } from '@/service/support/wallet/sub/utils';
|
||||
|
||||
export default withNextCors(async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
|
||||
try {
|
||||
@@ -37,8 +38,8 @@ export default withNextCors(async function handler(req: NextApiRequest, res: Nex
|
||||
// auth dataset limit
|
||||
await checkDatasetLimit({
|
||||
teamId,
|
||||
freeSize: global.feConfigs?.subscription?.datasetStoreFreeSize,
|
||||
insertLen: predictDataLimitLength(collection.trainingType, data)
|
||||
insertLen: predictDataLimitLength(collection.trainingType, data),
|
||||
standardPlans: getStandardSubPlan()
|
||||
});
|
||||
|
||||
jsonRes<PushDatasetDataResponse>(res, {
|
||||
|
||||
@@ -5,6 +5,7 @@ import { authDataset } from '@fastgpt/service/support/permission/auth/dataset';
|
||||
import { delDatasetRelevantData } from '@fastgpt/service/core/dataset/controller';
|
||||
import { findDatasetAndAllChildren } from '@fastgpt/service/core/dataset/controller';
|
||||
import { MongoDataset } from '@fastgpt/service/core/dataset/schema';
|
||||
import { mongoSessionRun } from '@fastgpt/service/common/mongo/sessionRun';
|
||||
|
||||
export default async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
|
||||
try {
|
||||
@@ -32,11 +33,15 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
|
||||
});
|
||||
|
||||
// delete all dataset.data and pg data
|
||||
await delDatasetRelevantData({ datasets });
|
||||
|
||||
// delete dataset data
|
||||
await MongoDataset.deleteMany({
|
||||
_id: { $in: datasets.map((d) => d._id) }
|
||||
await mongoSessionRun(async (session) => {
|
||||
// delete dataset data
|
||||
await delDatasetRelevantData({ datasets, session });
|
||||
await MongoDataset.deleteMany(
|
||||
{
|
||||
_id: { $in: datasets.map((d) => d._id) }
|
||||
},
|
||||
{ session }
|
||||
);
|
||||
});
|
||||
|
||||
jsonRes(res);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import type { NextApiRequest, NextApiResponse } from 'next';
|
||||
import { jsonRes } from '@fastgpt/service/common/response';
|
||||
import { connectToDatabase } from '@/service/mongo';
|
||||
import { getQAModel, getVectorModel } from '@/service/core/ai/model';
|
||||
import { getLLMModel, getVectorModel } from '@/service/core/ai/model';
|
||||
import type { DatasetItemType } from '@fastgpt/global/core/dataset/type.d';
|
||||
import { authDataset } from '@fastgpt/service/support/permission/auth/dataset';
|
||||
|
||||
@@ -29,7 +29,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
|
||||
data: {
|
||||
...dataset,
|
||||
vectorModel: getVectorModel(dataset.vectorModel),
|
||||
agentModel: getQAModel(dataset.agentModel),
|
||||
agentModel: getLLMModel(dataset.agentModel),
|
||||
canWrite,
|
||||
isOwner
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ export default withNextCors(async function handler(req: NextApiRequest, res: Nex
|
||||
// query extension
|
||||
// const { queries } = await searchQueryExtension({
|
||||
// query: text,
|
||||
// model: global.chatModels[0].model
|
||||
// model: global.llmModel[0].model
|
||||
// });
|
||||
|
||||
const { searchRes, charsLength, ...result } = await searchDatasetData({
|
||||
|
||||
@@ -17,6 +17,21 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
|
||||
|
||||
await authRequestFromLocal({ req });
|
||||
|
||||
// string all value
|
||||
Object.keys(obj).forEach((key) => {
|
||||
let val = obj[key];
|
||||
|
||||
if (typeof val === 'object') {
|
||||
val = JSON.stringify(val);
|
||||
} else if (typeof val === 'number') {
|
||||
val = String(val);
|
||||
} else if (typeof val === 'boolean') {
|
||||
val = val ? 'true' : 'false';
|
||||
}
|
||||
|
||||
obj[key] = val;
|
||||
});
|
||||
|
||||
const textResult = replaceVariable(text, obj);
|
||||
|
||||
res.json({
|
||||
|
||||
@@ -20,7 +20,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
|
||||
|
||||
const nanoid = customAlphabet(
|
||||
'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890',
|
||||
Math.floor(Math.random() * 14) + 24
|
||||
Math.floor(Math.random() * 14) + 52
|
||||
);
|
||||
const apiKey = `${global.systemEnv?.openapiPrefix || 'fastgpt'}-${nanoid()}`;
|
||||
|
||||
|
||||
@@ -20,7 +20,9 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
|
||||
const baseUrl = openaiAccount?.baseUrl || openaiBaseUrl;
|
||||
openaiAccount.baseUrl = baseUrl;
|
||||
|
||||
const ai = getAIApi(openaiAccount);
|
||||
const ai = getAIApi({
|
||||
userKey: openaiAccount
|
||||
});
|
||||
|
||||
const response = await ai.chat.completions.create({
|
||||
model: 'gpt-3.5-turbo',
|
||||
|
||||
@@ -3,6 +3,7 @@ import { jsonRes } from '@fastgpt/service/common/response';
|
||||
import { connectToDatabase } from '@/service/mongo';
|
||||
import { authCert } from '@fastgpt/service/support/permission/auth/common';
|
||||
import { checkDatasetLimit } from '@fastgpt/service/support/permission/limit/dataset';
|
||||
import { getStandardSubPlan } from '@/service/support/wallet/sub/utils';
|
||||
|
||||
export default async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
|
||||
try {
|
||||
@@ -22,8 +23,8 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
|
||||
|
||||
await checkDatasetLimit({
|
||||
teamId,
|
||||
freeSize: global.feConfigs?.subscription?.datasetStoreFreeSize,
|
||||
insertLen: numberSize
|
||||
insertLen: numberSize,
|
||||
standardPlans: getStandardSubPlan()
|
||||
});
|
||||
|
||||
jsonRes(res);
|
||||
|
||||
@@ -3,7 +3,7 @@ import { jsonRes } from '@fastgpt/service/common/response';
|
||||
import { connectToDatabase } from '@/service/mongo';
|
||||
import { BillSourceEnum } from '@fastgpt/global/support/wallet/bill/constants';
|
||||
import { CreateTrainingBillProps } from '@fastgpt/global/support/wallet/bill/api.d';
|
||||
import { getQAModel, getVectorModel } from '@/service/core/ai/model';
|
||||
import { getLLMModel, getVectorModel } from '@/service/core/ai/model';
|
||||
import { createTrainingBill } from '@fastgpt/service/support/wallet/bill/controller';
|
||||
import { authDataset } from '@fastgpt/service/support/permission/auth/dataset';
|
||||
|
||||
@@ -26,7 +26,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
|
||||
appName: name,
|
||||
billSource: BillSourceEnum.training,
|
||||
vectorModel: getVectorModel(dataset.vectorModel).name,
|
||||
agentModel: getQAModel(dataset.agentModel).name
|
||||
agentModel: getLLMModel(dataset.agentModel).name
|
||||
});
|
||||
|
||||
jsonRes<string>(res, {
|
||||
|
||||
@@ -2,8 +2,9 @@ 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 { getTeamDatasetValidSub } from '@fastgpt/service/support/wallet/sub/utils';
|
||||
import { getVectorCountByTeamId } from '@fastgpt/service/common/vectorStore/controller';
|
||||
import { getTeamSubPlanStatus } from '@fastgpt/service/support/wallet/sub/utils';
|
||||
import { getStandardSubPlan } from '@/service/support/wallet/sub/utils';
|
||||
import { FeTeamSubType } from '@fastgpt/global/support/wallet/sub/type';
|
||||
|
||||
export default async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
|
||||
try {
|
||||
@@ -15,20 +16,11 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
|
||||
authToken: true
|
||||
});
|
||||
|
||||
const [{ sub, maxSize }, usedSize] = await Promise.all([
|
||||
getTeamDatasetValidSub({
|
||||
jsonRes<FeTeamSubType>(res, {
|
||||
data: await getTeamSubPlanStatus({
|
||||
teamId,
|
||||
freeSize: global.feConfigs?.subscription?.datasetStoreFreeSize
|
||||
}),
|
||||
getVectorCountByTeamId(teamId)
|
||||
]);
|
||||
|
||||
jsonRes(res, {
|
||||
data: {
|
||||
sub,
|
||||
maxSize,
|
||||
usedSize
|
||||
}
|
||||
standardPlans: getStandardSubPlan()
|
||||
})
|
||||
});
|
||||
} catch (err) {
|
||||
jsonRes(res, {
|
||||
@@ -5,12 +5,15 @@ import { withNextCors } from '@fastgpt/service/common/middle/cors';
|
||||
import { pushGenerateVectorBill } from '@/service/support/wallet/bill/push';
|
||||
import { connectToDatabase } from '@/service/mongo';
|
||||
import { authTeamBalance } from '@/service/support/permission/auth/bill';
|
||||
import { getVectorsByText, GetVectorProps } from '@fastgpt/service/core/ai/embedding';
|
||||
import { getVectorsByText } from '@fastgpt/service/core/ai/embedding';
|
||||
import { updateApiKeyUsage } from '@fastgpt/service/support/openapi/tools';
|
||||
import { getBillSourceByAuthType } from '@fastgpt/global/support/wallet/bill/tools';
|
||||
import { getVectorModel } from '@/service/core/ai/model';
|
||||
|
||||
type Props = GetVectorProps & {
|
||||
type Props = {
|
||||
input: string | string[];
|
||||
model: string;
|
||||
dimensions?: number;
|
||||
billId?: string;
|
||||
};
|
||||
|
||||
@@ -33,7 +36,10 @@ export default withNextCors(async function handler(req: NextApiRequest, res: Nex
|
||||
|
||||
await authTeamBalance(teamId);
|
||||
|
||||
const { charsLength, vectors } = await getVectorsByText({ input: query, model });
|
||||
const { charsLength, vectors } = await getVectorsByText({
|
||||
input: query,
|
||||
model: getVectorModel(model)
|
||||
});
|
||||
|
||||
res.json({
|
||||
object: 'list',
|
||||
|
||||
@@ -15,7 +15,7 @@ import ChatTest, { type ChatTestComponentRef } from '@/components/core/module/Fl
|
||||
import { getFlowStore } from '@/components/core/module/Flow/FlowProvider';
|
||||
import { flowNode2Modules, filterExportModules } from '@/components/core/module/utils';
|
||||
import { useAppStore } from '@/web/core/app/store/useAppStore';
|
||||
import { useToast } from '@/web/common/hooks/useToast';
|
||||
import { useToast } from '@fastgpt/web/hooks/useToast';
|
||||
import { useConfirm } from '@/web/common/hooks/useConfirm';
|
||||
|
||||
const ImportSettings = dynamic(() => import('@/components/core/module/Flow/ImportSettings'));
|
||||
|
||||
@@ -12,7 +12,7 @@ import {
|
||||
} from '@chakra-ui/react';
|
||||
import { useForm } from 'react-hook-form';
|
||||
import { AppSchema } from '@fastgpt/global/core/app/type.d';
|
||||
import { useToast } from '@/web/common/hooks/useToast';
|
||||
import { useToast } from '@fastgpt/web/hooks/useToast';
|
||||
import { useSelectFile } from '@/web/common/file/hooks/useSelectFile';
|
||||
import { compressImgFileAndUpload } from '@/web/common/file/controller';
|
||||
import { getErrText } from '@fastgpt/global/common/error/utils';
|
||||
|
||||
@@ -9,7 +9,7 @@ import MyIcon from '@fastgpt/web/components/common/Icon';
|
||||
import { useCopyData } from '@/web/common/hooks/useCopyData';
|
||||
import { useSelectFile } from '@/web/common/file/hooks/useSelectFile';
|
||||
import { fileToBase64 } from '@/web/common/file/utils';
|
||||
import { feConfigs } from '@/web/common/system/staticData';
|
||||
import { useSystemStore } from '@/web/common/system/useSystemStore';
|
||||
|
||||
enum UsingWayEnum {
|
||||
link = 'link',
|
||||
@@ -25,6 +25,7 @@ const SelectUsingWayModal = ({ share, onClose }: { share: OutLinkSchema; onClose
|
||||
multiple: false,
|
||||
fileType: 'image/*'
|
||||
});
|
||||
const { feConfigs } = useSystemStore();
|
||||
|
||||
const VariableTypeList = [
|
||||
{
|
||||
|
||||
@@ -39,19 +39,21 @@ import { useRequest } from '@/web/common/hooks/useRequest';
|
||||
import { formatStorePrice2Read } from '@fastgpt/global/support/wallet/bill/tools';
|
||||
import { OutLinkTypeEnum } from '@fastgpt/global/support/outLink/constant';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import { useToast } from '@/web/common/hooks/useToast';
|
||||
import { feConfigs } from '@/web/common/system/staticData';
|
||||
import { useToast } from '@fastgpt/web/hooks/useToast';
|
||||
import { useSystemStore } from '@/web/common/system/useSystemStore';
|
||||
import MyTooltip from '@/components/MyTooltip';
|
||||
import MyModal from '@/components/MyModal';
|
||||
import dayjs from 'dayjs';
|
||||
import { getDocPath } from '@/web/common/system/doc';
|
||||
import dynamic from 'next/dynamic';
|
||||
import MyMenu from '@/components/MyMenu';
|
||||
|
||||
const SelectUsingWayModal = dynamic(() => import('./SelectUsingWayModal'));
|
||||
|
||||
const Share = ({ appId }: { appId: string }) => {
|
||||
const { t } = useTranslation();
|
||||
const { Loading, setIsLoading } = useLoading();
|
||||
const { feConfigs } = useSystemStore();
|
||||
const { copyData } = useCopyData();
|
||||
const [editLinkData, setEditLinkData] = useState<OutLinkEditType>();
|
||||
const [selectedLinkData, setSelectedLinkData] = useState<OutLinkSchema>();
|
||||
@@ -135,40 +137,40 @@ const Share = ({ appId }: { appId: string }) => {
|
||||
{item.lastTime ? t(formatTimeToChatTime(item.lastTime)) : t('common.Un used')}
|
||||
</Td>
|
||||
<Td display={'flex'} alignItems={'center'}>
|
||||
<Menu autoSelect={false} isLazy>
|
||||
<MenuButton
|
||||
_hover={{ bg: 'myWhite.600 ' }}
|
||||
cursor={'pointer'}
|
||||
borderRadius={'md'}
|
||||
>
|
||||
<MyIcon name={'more'} w={'14px'} p={2} />
|
||||
</MenuButton>
|
||||
<MenuList color={'myGray.700'} minW={`120px !important`} zIndex={10}>
|
||||
<MenuItem
|
||||
onClick={() => {
|
||||
<MyMenu
|
||||
Button={
|
||||
<MyIcon
|
||||
name={'more'}
|
||||
_hover={{ bg: 'myGray.100 ' }}
|
||||
cursor={'pointer'}
|
||||
borderRadius={'md'}
|
||||
w={'14px'}
|
||||
p={2}
|
||||
/>
|
||||
}
|
||||
menuList={[
|
||||
{
|
||||
label: t('core.app.outLink.Select Mode'),
|
||||
icon: 'copy',
|
||||
onClick: () => {
|
||||
setSelectedLinkData(item);
|
||||
}}
|
||||
py={[2, 3]}
|
||||
>
|
||||
<MyIcon name={'copy'} w={['14px', '16px']} />
|
||||
<Box ml={[1, 2]}>{t('core.app.outLink.Select Mode')}</Box>
|
||||
</MenuItem>
|
||||
<MenuItem
|
||||
onClick={() =>
|
||||
}
|
||||
},
|
||||
{
|
||||
label: t('common.Edit'),
|
||||
icon: 'edit',
|
||||
onClick: () =>
|
||||
setEditLinkData({
|
||||
_id: item._id,
|
||||
name: item.name,
|
||||
responseDetail: item.responseDetail,
|
||||
limit: item.limit
|
||||
})
|
||||
}
|
||||
py={[2, 3]}
|
||||
>
|
||||
<MyIcon name={'edit'} w={['14px', '16px']} />
|
||||
<Box ml={[1, 2]}>{t('common.Edit')}</Box>
|
||||
</MenuItem>
|
||||
<MenuItem
|
||||
onClick={async () => {
|
||||
},
|
||||
{
|
||||
label: t('common.Delete'),
|
||||
icon: 'delete',
|
||||
onClick: async () => {
|
||||
setIsLoading(true);
|
||||
try {
|
||||
await delShareChatById(item._id);
|
||||
@@ -177,14 +179,10 @@ const Share = ({ appId }: { appId: string }) => {
|
||||
console.log(error);
|
||||
}
|
||||
setIsLoading(false);
|
||||
}}
|
||||
py={[2, 3]}
|
||||
>
|
||||
<MyIcon name={'delete'} w={['14px', '16px']} />
|
||||
<Box ml={[1, 2]}>{t('common.Delete')}</Box>
|
||||
</MenuItem>
|
||||
</MenuList>
|
||||
</Menu>
|
||||
}
|
||||
}
|
||||
]}
|
||||
/>
|
||||
</Td>
|
||||
</Tr>
|
||||
))}
|
||||
@@ -249,6 +247,7 @@ function EditLinkModal({
|
||||
onCreate: (id: string) => void;
|
||||
onEdit: () => void;
|
||||
}) {
|
||||
const { feConfigs } = useSystemStore();
|
||||
const { t } = useTranslation();
|
||||
const {
|
||||
register,
|
||||
|
||||
@@ -18,7 +18,7 @@ const OutLink = ({ appId }: { appId: string }) => {
|
||||
return (
|
||||
<Box pt={[1, 5]}>
|
||||
<Box fontWeight={'bold'} fontSize={['md', 'xl']} mb={2} px={[4, 8]}>
|
||||
{t('core.app.External using')}
|
||||
{t('core.app.navbar.Publish app')}
|
||||
</Box>
|
||||
<Box pb={[5, 7]} px={[4, 8]} borderBottom={theme.borders.base}>
|
||||
<MyRadio
|
||||
|
||||
@@ -3,7 +3,7 @@ import { Box, Flex, Button, IconButton } from '@chakra-ui/react';
|
||||
import { useRequest } from '@/web/common/hooks/useRequest';
|
||||
import { useConfirm } from '@/web/common/hooks/useConfirm';
|
||||
import { useRouter } from 'next/router';
|
||||
import { useToast } from '@/web/common/hooks/useToast';
|
||||
import { useToast } from '@fastgpt/web/hooks/useToast';
|
||||
import { AppSchema } from '@fastgpt/global/core/app/type.d';
|
||||
import { delModelById } from '@/web/core/app/api';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
@@ -116,12 +116,12 @@ const AppCard = ({ appId }: { appId: string }) => {
|
||||
router.replace({
|
||||
query: {
|
||||
appId,
|
||||
currentTab: 'outLink'
|
||||
currentTab: 'publish'
|
||||
}
|
||||
});
|
||||
}}
|
||||
>
|
||||
{t('core.app.navbar.External')}
|
||||
{t('core.app.navbar.Publish')}
|
||||
</Button>
|
||||
{appDetail.isOwner && (
|
||||
<Button
|
||||
|
||||
@@ -18,7 +18,6 @@ const CfrEditModal = ({
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
const [value, setValue] = useState(defaultValue);
|
||||
const [, startTst] = useTransition();
|
||||
|
||||
return (
|
||||
<MyModal
|
||||
@@ -38,12 +37,10 @@ const CfrEditModal = ({
|
||||
h={200}
|
||||
showOpenModal={false}
|
||||
placeholder={t('core.module.input.placeholder.cfr background')}
|
||||
defaultValue={value}
|
||||
onChange={useCallback((e: string) => {
|
||||
startTst(() => {
|
||||
setValue(e);
|
||||
});
|
||||
}, [])}
|
||||
value={value}
|
||||
onChange={(e) => {
|
||||
setValue(e);
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
</ModalBody>
|
||||
|
||||
@@ -49,7 +49,7 @@ const ChatTest = ({ appId }: { appId: string }) => {
|
||||
appName: `调试-${appDetail.name}`
|
||||
},
|
||||
onMessage: generatingMessage,
|
||||
abortSignal: controller
|
||||
abortCtrl: controller
|
||||
});
|
||||
|
||||
return { responseText, responseData };
|
||||
|
||||
@@ -15,7 +15,6 @@ import { useForm, useFieldArray } from 'react-hook-form';
|
||||
import { useSystemStore } from '@/web/common/system/useSystemStore';
|
||||
import { appModules2Form, getDefaultAppForm } from '@fastgpt/global/core/app/utils';
|
||||
import type { AppSimpleEditFormType } from '@fastgpt/global/core/app/type.d';
|
||||
import { chatModelList, simpleModeTemplates } from '@/web/common/system/staticData';
|
||||
import { chatNodeSystemPromptTip, welcomeTextTip } from '@fastgpt/global/core/module/template/tip';
|
||||
import { useRequest } from '@/web/common/hooks/useRequest';
|
||||
import { useConfirm } from '@/web/common/hooks/useConfirm';
|
||||
@@ -37,7 +36,7 @@ import MyTextarea from '@/components/common/Textarea/MyTextarea/index';
|
||||
import { DatasetSearchModeMap } from '@fastgpt/global/core/dataset/constants';
|
||||
import SelectAiModel from '@/components/Select/SelectAiModel';
|
||||
import PromptEditor from '@fastgpt/web/components/common/Textarea/PromptEditor';
|
||||
import { formatVariablesIcon } from '@fastgpt/global/core/module/utils';
|
||||
import { formatEditorVariablePickerIcon } from '@fastgpt/global/core/module/utils';
|
||||
|
||||
const DatasetSelectModal = dynamic(() => import('@/components/core/module/DatasetSelectModal'));
|
||||
const DatasetParamsModal = dynamic(() => import('@/components/core/module/DatasetParamsModal'));
|
||||
@@ -60,7 +59,7 @@ const EditForm = ({
|
||||
const { t } = useTranslation();
|
||||
const { appDetail, updateAppDetail } = useAppStore();
|
||||
const { loadAllDatasets, allDatasets } = useDatasetStore();
|
||||
const { isPc } = useSystemStore();
|
||||
const { isPc, llmModelList, reRankModelList, simpleModeTemplates } = useSystemStore();
|
||||
const [refresh, setRefresh] = useState(false);
|
||||
const [, startTst] = useTransition();
|
||||
|
||||
@@ -100,12 +99,12 @@ const EditForm = ({
|
||||
});
|
||||
|
||||
const variables = watch('userGuide.variables');
|
||||
const formatVariables = useMemo(() => formatVariablesIcon(variables), [variables]);
|
||||
const formatVariables = useMemo(() => formatEditorVariablePickerIcon(variables), [variables]);
|
||||
const aiSystemPrompt = watch('aiSettings.systemPrompt');
|
||||
const searchMode = watch('dataset.searchMode');
|
||||
|
||||
const chatModelSelectList = (() =>
|
||||
chatModelList.map((item) => ({
|
||||
llmModelList.map((item) => ({
|
||||
value: item.model,
|
||||
label: item.name
|
||||
})))();
|
||||
@@ -121,10 +120,10 @@ const EditForm = ({
|
||||
|
||||
const tokenLimit = useMemo(() => {
|
||||
return (
|
||||
chatModelList.find((item) => item.model === getValues('aiSettings.model'))?.quoteMaxToken ||
|
||||
llmModelList.find((item) => item.model === getValues('aiSettings.model'))?.quoteMaxToken ||
|
||||
3000
|
||||
);
|
||||
}, [getValues, refresh]);
|
||||
}, [getValues, llmModelList]);
|
||||
|
||||
const datasetSearchMode = useMemo(() => {
|
||||
if (!searchMode) return '';
|
||||
@@ -280,7 +279,7 @@ const EditForm = ({
|
||||
onchange={(val: any) => {
|
||||
setValue('aiSettings.model', val);
|
||||
const maxToken =
|
||||
chatModelList.find((item) => item.model === getValues('aiSettings.model'))
|
||||
llmModelList.find((item) => item.model === getValues('aiSettings.model'))
|
||||
?.maxResponse || 4000;
|
||||
const token = maxToken / 2;
|
||||
setValue('aiSettings.maxToken', token);
|
||||
@@ -301,7 +300,7 @@ const EditForm = ({
|
||||
</Box>
|
||||
{isInitd && (
|
||||
<PromptEditor
|
||||
defaultValue={aiSystemPrompt}
|
||||
value={aiSystemPrompt}
|
||||
onChange={(text) => {
|
||||
startTst(() => {
|
||||
setValue('aiSettings.systemPrompt', text);
|
||||
@@ -350,6 +349,13 @@ const EditForm = ({
|
||||
<Flex mt={1} color={'myGray.600'} fontSize={'sm'} mb={2}>
|
||||
{t('core.dataset.search.search mode')}: {datasetSearchMode}
|
||||
{', '}
|
||||
{reRankModelList.length > 0 && (
|
||||
<>
|
||||
{t('core.dataset.search.ReRank')}:{' '}
|
||||
{getValues('dataset.usingReRank') ? '✅' : '✖'}
|
||||
</>
|
||||
)}
|
||||
{', '}
|
||||
{t('core.dataset.search.Min Similarity')}: {getValues('dataset.similarity')}
|
||||
{', '}
|
||||
{t('core.dataset.search.Max Tokens')}: {getValues('dataset.limit')}
|
||||
|
||||
@@ -2,9 +2,9 @@ import React, { useEffect, useMemo, useCallback } from 'react';
|
||||
import { useRouter } from 'next/router';
|
||||
import { Box, Flex, IconButton, useTheme } from '@chakra-ui/react';
|
||||
import dynamic from 'next/dynamic';
|
||||
import { useToast } from '@/web/common/hooks/useToast';
|
||||
import { useToast } from '@fastgpt/web/hooks/useToast';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { feConfigs } from '@/web/common/system/staticData';
|
||||
import { useSystemStore } from '@/web/common/system/useSystemStore';
|
||||
|
||||
import Tabs from '@/components/Tabs';
|
||||
import SideTabs from '@/components/SideTabs';
|
||||
@@ -27,7 +27,7 @@ const Logs = dynamic(() => import('./components/Logs'), {});
|
||||
enum TabEnum {
|
||||
'simpleEdit' = 'simpleEdit',
|
||||
'adEdit' = 'adEdit',
|
||||
'outLink' = 'outLink',
|
||||
'publish' = 'publish',
|
||||
'logs' = 'logs',
|
||||
'startChat' = 'startChat'
|
||||
}
|
||||
@@ -36,6 +36,7 @@ const AppDetail = ({ currentTab }: { currentTab: `${TabEnum}` }) => {
|
||||
const { t } = useTranslation();
|
||||
const router = useRouter();
|
||||
const theme = useTheme();
|
||||
const { feConfigs } = useSystemStore();
|
||||
const { toast } = useToast();
|
||||
const { appId } = router.query as { appId: string };
|
||||
const { appDetail, loadAppDetail, clearAppModules } = useAppStore();
|
||||
@@ -69,14 +70,14 @@ const AppDetail = ({ currentTab }: { currentTab: `${TabEnum}` }) => {
|
||||
}
|
||||
]),
|
||||
{
|
||||
label: t('core.app.navbar.External'),
|
||||
id: TabEnum.outLink,
|
||||
label: t('core.app.navbar.Publish app'),
|
||||
id: TabEnum.publish,
|
||||
icon: 'support/outlink/shareLight'
|
||||
},
|
||||
{ label: t('app.Chat logs'), id: TabEnum.logs, icon: 'core/app/logsLight' },
|
||||
{ label: t('core.Start chat'), id: TabEnum.startChat, icon: 'core/chat/chatLight' }
|
||||
],
|
||||
[t]
|
||||
[feConfigs?.hide_app_flow, t]
|
||||
);
|
||||
|
||||
const onCloseFlowEdit = useCallback(() => setCurrentTab(TabEnum.simpleEdit), [setCurrentTab]);
|
||||
@@ -194,7 +195,7 @@ const AppDetail = ({ currentTab }: { currentTab: `${TabEnum}` }) => {
|
||||
<FlowEdit app={appDetail} onClose={onCloseFlowEdit} />
|
||||
)}
|
||||
{currentTab === TabEnum.logs && <Logs appId={appId} />}
|
||||
{currentTab === TabEnum.outLink && <OutLink appId={appId} />}
|
||||
{currentTab === TabEnum.publish && <OutLink appId={appId} />}
|
||||
</Box>
|
||||
</Flex>
|
||||
</PageContainer>
|
||||
|
||||
@@ -14,13 +14,12 @@ import { useSelectFile } from '@/web/common/file/hooks/useSelectFile';
|
||||
import { useForm } from 'react-hook-form';
|
||||
import { compressImgFileAndUpload } from '@/web/common/file/controller';
|
||||
import { getErrText } from '@fastgpt/global/common/error/utils';
|
||||
import { useToast } from '@/web/common/hooks/useToast';
|
||||
import { useToast } from '@fastgpt/web/hooks/useToast';
|
||||
import { postCreateApp } from '@/web/core/app/api';
|
||||
import { useRouter } from 'next/router';
|
||||
import { appTemplates } from '@/web/core/app/templates';
|
||||
import { useSystemStore } from '@/web/common/system/useSystemStore';
|
||||
import { useRequest } from '@/web/common/hooks/useRequest';
|
||||
import { feConfigs } from '@/web/common/system/staticData';
|
||||
import Avatar from '@/components/Avatar';
|
||||
import MyTooltip from '@/components/MyTooltip';
|
||||
import MyModal from '@/components/MyModal';
|
||||
@@ -39,7 +38,7 @@ const CreateModal = ({ onClose, onSuccess }: { onClose: () => void; onSuccess: (
|
||||
const { toast } = useToast();
|
||||
const router = useRouter();
|
||||
const theme = useTheme();
|
||||
const { isPc } = useSystemStore();
|
||||
const { isPc, feConfigs } = useSystemStore();
|
||||
const { register, setValue, getValues, handleSubmit } = useForm<FormType>({
|
||||
defaultValues: {
|
||||
avatar: '/icon/logo.svg',
|
||||
|
||||
@@ -1,20 +1,10 @@
|
||||
import React, { useCallback, useEffect } from 'react';
|
||||
import {
|
||||
Box,
|
||||
Grid,
|
||||
Card,
|
||||
useTheme,
|
||||
Flex,
|
||||
IconButton,
|
||||
Button,
|
||||
useDisclosure,
|
||||
Image
|
||||
} from '@chakra-ui/react';
|
||||
import React, { useCallback } from 'react';
|
||||
import { Box, Grid, Flex, IconButton, Button, useDisclosure } from '@chakra-ui/react';
|
||||
import { useRouter } from 'next/router';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { AddIcon } from '@chakra-ui/icons';
|
||||
import { delModelById } from '@/web/core/app/api';
|
||||
import { useToast } from '@/web/common/hooks/useToast';
|
||||
import { useToast } from '@fastgpt/web/hooks/useToast';
|
||||
import { useConfirm } from '@/web/common/hooks/useConfirm';
|
||||
import { serviceSideProps } from '@/web/common/utils/i18n';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
@@ -31,7 +21,6 @@ import { useUserStore } from '@/web/support/user/useUserStore';
|
||||
const MyApps = () => {
|
||||
const { toast } = useToast();
|
||||
const { t } = useTranslation();
|
||||
const theme = useTheme();
|
||||
const router = useRouter();
|
||||
const { userInfo } = useUserStore();
|
||||
const { myApps, loadMyApps } = useAppStore();
|
||||
@@ -76,9 +65,11 @@ const MyApps = () => {
|
||||
<Box letterSpacing={1} fontSize={['20px', '24px']} color={'myGray.900'}>
|
||||
{t('app.My Apps')}
|
||||
</Box>
|
||||
<Button leftIcon={<AddIcon />} variant={'primaryOutline'} onClick={onOpenCreateModal}>
|
||||
{t('common.New Create')}
|
||||
</Button>
|
||||
{userInfo?.team?.canWrite && (
|
||||
<Button leftIcon={<AddIcon />} variant={'primaryOutline'} onClick={onOpenCreateModal}>
|
||||
{t('common.New Create')}
|
||||
</Button>
|
||||
)}
|
||||
</Flex>
|
||||
<Grid
|
||||
py={[4, 6]}
|
||||
|
||||
@@ -16,7 +16,7 @@ import { useQuery } from '@tanstack/react-query';
|
||||
import { streamFetch } from '@/web/common/api/fetch';
|
||||
import { useChatStore } from '@/web/core/chat/storeChat';
|
||||
import { useLoading } from '@/web/common/hooks/useLoading';
|
||||
import { useToast } from '@/web/common/hooks/useToast';
|
||||
import { useToast } from '@fastgpt/web/hooks/useToast';
|
||||
import { customAlphabet } from 'nanoid';
|
||||
const nanoid = customAlphabet('abcdefghijklmnopqrstuvwxyz1234567890', 12);
|
||||
import type { ChatHistoryItemType } from '@fastgpt/global/core/chat/type.d';
|
||||
@@ -80,7 +80,7 @@ const Chat = ({ appId, chatId }: { appId: string; chatId: string }) => {
|
||||
chatId: completionChatId
|
||||
},
|
||||
onMessage: generatingMessage,
|
||||
abortSignal: controller
|
||||
abortCtrl: controller
|
||||
});
|
||||
|
||||
const newTitle =
|
||||
@@ -126,7 +126,7 @@ const Chat = ({ appId, chatId }: { appId: string; chatId: string }) => {
|
||||
|
||||
return { responseText, responseData, isNewChat: forbidRefresh.current };
|
||||
},
|
||||
[appId, chatId, histories, pushHistory, router, setChatData, updateHistory]
|
||||
[appId, chatId, histories, pushHistory, router, setChatData, t, updateHistory]
|
||||
);
|
||||
|
||||
// get chat app info
|
||||
@@ -183,7 +183,7 @@ const Chat = ({ appId, chatId }: { appId: string; chatId: string }) => {
|
||||
setIsLoading(false);
|
||||
return null;
|
||||
},
|
||||
[setIsLoading, setChatData, router, setLastChatAppId, setLastChatId, toast]
|
||||
[setIsLoading, setChatData, setLastChatAppId, setLastChatId, toast, t, router]
|
||||
);
|
||||
// 初始化聊天框
|
||||
useQuery(['init', { appId, chatId }], () => {
|
||||
|
||||
@@ -2,7 +2,7 @@ import React, { useCallback, useEffect, useRef, useState } from 'react';
|
||||
import Head from 'next/head';
|
||||
import { useRouter } from 'next/router';
|
||||
import { Box, Flex, useDisclosure, Drawer, DrawerOverlay, DrawerContent } from '@chakra-ui/react';
|
||||
import { useToast } from '@/web/common/hooks/useToast';
|
||||
import { useToast } from '@fastgpt/web/hooks/useToast';
|
||||
import { useSystemStore } from '@/web/common/system/useSystemStore';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { streamFetch } from '@/web/common/api/fetch';
|
||||
@@ -82,7 +82,7 @@ const OutLink = ({
|
||||
outLinkUid
|
||||
},
|
||||
onMessage: generatingMessage,
|
||||
abortSignal: controller
|
||||
abortCtrl: controller
|
||||
});
|
||||
|
||||
const newTitle =
|
||||
|
||||
@@ -55,7 +55,7 @@ import ParentPath from '@/components/common/ParentPaths';
|
||||
import dynamic from 'next/dynamic';
|
||||
import { useDrag } from '@/web/common/hooks/useDrag';
|
||||
import SelectCollections from '@/web/core/dataset/components/SelectCollections';
|
||||
import { useToast } from '@/web/common/hooks/useToast';
|
||||
import { useToast } from '@fastgpt/web/hooks/useToast';
|
||||
import MyTooltip from '@/components/MyTooltip';
|
||||
import { useUserStore } from '@/web/support/user/useUserStore';
|
||||
import { TeamMemberRoleEnum } from '@fastgpt/global/support/user/team/constant';
|
||||
@@ -381,8 +381,7 @@ const CollectionCard = () => {
|
||||
<>
|
||||
{userInfo?.team?.role !== TeamMemberRoleEnum.visitor && (
|
||||
<MyMenu
|
||||
offset={[-0, 10]}
|
||||
width={120}
|
||||
offset={[0, 5]}
|
||||
Button={
|
||||
<MenuButton
|
||||
_hover={{
|
||||
@@ -408,7 +407,7 @@ const CollectionCard = () => {
|
||||
}
|
||||
menuList={[
|
||||
{
|
||||
child: (
|
||||
label: (
|
||||
<Flex>
|
||||
<MyIcon name={'common/folderFill'} w={'20px'} mr={2} />
|
||||
{t('Folder')}
|
||||
@@ -417,7 +416,7 @@ const CollectionCard = () => {
|
||||
onClick: () => setEditFolderData({})
|
||||
},
|
||||
{
|
||||
child: (
|
||||
label: (
|
||||
<Flex>
|
||||
<MyIcon name={'core/dataset/manualCollection'} mr={2} w={'20px'} />
|
||||
{t('core.dataset.Manual collection')}
|
||||
@@ -433,7 +432,7 @@ const CollectionCard = () => {
|
||||
}
|
||||
},
|
||||
{
|
||||
child: (
|
||||
label: (
|
||||
<Flex>
|
||||
<MyIcon name={'core/dataset/fileCollection'} mr={2} w={'20px'} />
|
||||
{t('core.dataset.Text collection')}
|
||||
@@ -442,7 +441,7 @@ const CollectionCard = () => {
|
||||
onClick: onOpenFileSourceSelector
|
||||
},
|
||||
{
|
||||
child: (
|
||||
label: (
|
||||
<Flex>
|
||||
<MyIcon name={'core/dataset/tableCollection'} mr={2} w={'20px'} />
|
||||
{t('core.dataset.Table collection')}
|
||||
@@ -627,6 +626,7 @@ const CollectionCard = () => {
|
||||
{collection.canWrite && userInfo?.team?.role !== TeamMemberRoleEnum.visitor && (
|
||||
<MyMenu
|
||||
width={100}
|
||||
offset={[-70, 5]}
|
||||
Button={
|
||||
<MenuButton
|
||||
w={'22px'}
|
||||
@@ -655,7 +655,7 @@ const CollectionCard = () => {
|
||||
...(collection.type === DatasetCollectionTypeEnum.link
|
||||
? [
|
||||
{
|
||||
child: (
|
||||
label: (
|
||||
<Flex alignItems={'center'}>
|
||||
<MyIcon name={'common/refreshLight'} w={'14px'} mr={2} />
|
||||
{t('core.dataset.collection.Sync')}
|
||||
@@ -669,7 +669,7 @@ const CollectionCard = () => {
|
||||
]
|
||||
: []),
|
||||
{
|
||||
child: (
|
||||
label: (
|
||||
<Flex alignItems={'center'}>
|
||||
<MyIcon name={'common/file/move'} w={'14px'} mr={2} />
|
||||
{t('Move')}
|
||||
@@ -678,7 +678,7 @@ const CollectionCard = () => {
|
||||
onClick: () => setMoveCollectionData({ collectionId: collection._id })
|
||||
},
|
||||
{
|
||||
child: (
|
||||
label: (
|
||||
<Flex alignItems={'center'}>
|
||||
<MyIcon name={'edit'} w={'14px'} mr={2} />
|
||||
{t('Rename')}
|
||||
@@ -696,7 +696,7 @@ const CollectionCard = () => {
|
||||
})
|
||||
},
|
||||
{
|
||||
child: (
|
||||
label: (
|
||||
<Flex alignItems={'center'}>
|
||||
<MyIcon
|
||||
mr={1}
|
||||
|
||||
@@ -23,7 +23,7 @@ import {
|
||||
} from '@/web/core/dataset/api';
|
||||
import { DeleteIcon } from '@chakra-ui/icons';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { useToast } from '@/web/common/hooks/useToast';
|
||||
import { useToast } from '@fastgpt/web/hooks/useToast';
|
||||
import { debounce } from 'lodash';
|
||||
import { getErrText } from '@fastgpt/global/common/error/utils';
|
||||
import { useConfirm } from '@/web/common/hooks/useConfirm';
|
||||
|
||||
@@ -3,11 +3,11 @@ import MyModal from '@/components/MyModal';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import { Box, Button, Input, Link, ModalBody, ModalFooter } from '@chakra-ui/react';
|
||||
import { strIsLink } from '@fastgpt/global/common/string/tools';
|
||||
import { useToast } from '@/web/common/hooks/useToast';
|
||||
import { useToast } from '@fastgpt/web/hooks/useToast';
|
||||
import { useForm } from 'react-hook-form';
|
||||
import { useConfirm } from '@/web/common/hooks/useConfirm';
|
||||
import { getDocPath } from '@/web/common/system/doc';
|
||||
import { feConfigs } from '@/web/common/system/staticData';
|
||||
import { useSystemStore } from '@/web/common/system/useSystemStore';
|
||||
|
||||
type FormType = {
|
||||
url?: string | undefined;
|
||||
@@ -27,6 +27,7 @@ const WebsiteConfigModal = ({
|
||||
defaultValue?: FormType;
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
const { feConfigs } = useSystemStore();
|
||||
const { toast } = useToast();
|
||||
const { register, handleSubmit } = useForm({
|
||||
defaultValues: defaultValue
|
||||
|
||||
@@ -21,8 +21,8 @@ import { TrainingTypeMap } from '@fastgpt/global/core/dataset/constants';
|
||||
import { ImportProcessWayEnum } from '@/web/core/dataset/constants';
|
||||
import MyTooltip from '@/components/MyTooltip';
|
||||
import { useImportStore } from '../Provider';
|
||||
import { feConfigs } from '@/web/common/system/staticData';
|
||||
import Tag from '@/components/Tag';
|
||||
import { useSystemStore } from '@/web/common/system/useSystemStore';
|
||||
import MyModal from '@/components/MyModal';
|
||||
import { Prompt_AgentQA } from '@/global/core/prompt/agent';
|
||||
import Preview from '../components/Preview';
|
||||
@@ -35,6 +35,7 @@ function DataProcess({
|
||||
goToNext: () => void;
|
||||
}) {
|
||||
const { t } = useTranslation();
|
||||
const { feConfigs } = useSystemStore();
|
||||
const {
|
||||
processParamsForm,
|
||||
sources,
|
||||
|
||||
@@ -21,7 +21,7 @@ import { useDatasetStore } from '@/web/core/dataset/store/dataset';
|
||||
import { chunksUpload, fileCollectionCreate } from '@/web/core/dataset/utils';
|
||||
import { ImportSourceItemType } from '@/web/core/dataset/type';
|
||||
import { hashStr } from '@fastgpt/global/common/string/tools';
|
||||
import { useToast } from '@/web/common/hooks/useToast';
|
||||
import { useToast } from '@fastgpt/web/hooks/useToast';
|
||||
import { useRouter } from 'next/router';
|
||||
import { TabEnum } from '../../../index';
|
||||
import { postCreateDatasetLinkCollection, postDatasetCollection } from '@/web/core/dataset/api';
|
||||
|
||||
@@ -29,7 +29,7 @@ const Preview = ({
|
||||
.map((source) =>
|
||||
source.chunks.slice(0, oneSourceChunkLength).map((chunk, i) => ({
|
||||
...chunk,
|
||||
chunkIndex: i + 1,
|
||||
index: i + 1,
|
||||
sourceName: source.sourceName,
|
||||
sourceIcon: source.icon
|
||||
}))
|
||||
@@ -86,7 +86,7 @@ const Preview = ({
|
||||
bg={'primary.50'}
|
||||
borderRadius={'sm'}
|
||||
>
|
||||
# {chunk.chunkIndex}
|
||||
# {chunk.index}
|
||||
</Box>
|
||||
<Flex ml={2} fontWeight={'bold'} alignItems={'center'} gap={1}>
|
||||
<MyIcon name={chunk.sourceIcon as any} w={'14px'} />
|
||||
|
||||
@@ -9,7 +9,7 @@ import { Box, Button, Flex, Input, Link, Textarea } from '@chakra-ui/react';
|
||||
import { getNanoid } from '@fastgpt/global/common/string/tools';
|
||||
import MyIcon from '@fastgpt/web/components/common/Icon';
|
||||
import { LinkCollectionIcon } from '@fastgpt/global/core/dataset/constants';
|
||||
import { feConfigs } from '@/web/common/system/staticData';
|
||||
import { useSystemStore } from '@/web/common/system/useSystemStore';
|
||||
import { getDocPath } from '@/web/common/system/doc';
|
||||
import Loading from '@/components/Loading';
|
||||
|
||||
@@ -32,6 +32,7 @@ export default React.memo(LinkCollection);
|
||||
|
||||
const CustomLinkImport = ({ goToNext }: { goToNext: () => void }) => {
|
||||
const { t } = useTranslation();
|
||||
const { feConfigs } = useSystemStore();
|
||||
const { sources, setSources, processParamsForm } = useImportStore();
|
||||
const { register, reset, handleSubmit, watch } = useForm({
|
||||
defaultValues: {
|
||||
|
||||
@@ -15,7 +15,7 @@ import { MongoImageTypeEnum } from '@fastgpt/global/common/file/image/constants'
|
||||
import MyTooltip from '@/components/MyTooltip';
|
||||
import type { PreviewRawTextProps } from '../components/PreviewRawText';
|
||||
import { useImportStore } from '../Provider';
|
||||
import { feConfigs } from '@/web/common/system/staticData';
|
||||
import { useSystemStore } from '@/web/common/system/useSystemStore';
|
||||
|
||||
import dynamic from 'next/dynamic';
|
||||
import Loading from '@/components/Loading';
|
||||
@@ -44,6 +44,7 @@ export default React.memo(FileLocal);
|
||||
|
||||
const SelectFile = React.memo(function SelectFile({ goToNext }: { goToNext: () => void }) {
|
||||
const { t } = useTranslation();
|
||||
const { feConfigs } = useSystemStore();
|
||||
const { sources, setSources } = useImportStore();
|
||||
// @ts-ignore
|
||||
const [selectFiles, setSelectFiles] = useState<FileItemType[]>(sources);
|
||||
|
||||
@@ -11,7 +11,7 @@ import { getNanoid } from '@fastgpt/global/common/string/tools';
|
||||
import { useRequest } from '@/web/common/hooks/useRequest';
|
||||
import MyTooltip from '@/components/MyTooltip';
|
||||
import { useImportStore } from '../Provider';
|
||||
import { feConfigs } from '@/web/common/system/staticData';
|
||||
import { useSystemStore } from '@/web/common/system/useSystemStore';
|
||||
|
||||
import dynamic from 'next/dynamic';
|
||||
import { fileDownload } from '@/web/common/file/utils';
|
||||
@@ -43,6 +43,7 @@ const csvTemplate = `index,content
|
||||
|
||||
const SelectFile = React.memo(function SelectFile({ goToNext }: { goToNext: () => void }) {
|
||||
const { t } = useTranslation();
|
||||
const { feConfigs } = useSystemStore();
|
||||
const { sources, setSources } = useImportStore();
|
||||
// @ts-ignore
|
||||
const [selectFiles, setSelectFiles] = useState<FileItemType[]>(sources);
|
||||
@@ -61,10 +62,10 @@ const SelectFile = React.memo(function SelectFile({ goToNext }: { goToNext: () =
|
||||
|
||||
const filterData: FileItemType['chunks'] = data
|
||||
.filter((item) => item[0])
|
||||
.map((item, i) => ({
|
||||
.map((item) => ({
|
||||
q: item[0] || '',
|
||||
a: item[1] || '',
|
||||
chunkIndex: i
|
||||
chunkIndex: 0
|
||||
}));
|
||||
|
||||
const item: FileItemType = {
|
||||
|
||||
@@ -14,7 +14,7 @@ import MyTooltip from '@/components/MyTooltip';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import PermissionRadio from '@/components/support/permission/Radio';
|
||||
import MySelect from '@/components/Select';
|
||||
import { qaModelList, vectorModelList } from '@/web/common/system/staticData';
|
||||
import { useSystemStore } from '@/web/common/system/useSystemStore';
|
||||
import { useRequest } from '@/web/common/hooks/useRequest';
|
||||
import { MongoImageTypeEnum } from '@fastgpt/global/common/file/image/constants';
|
||||
|
||||
@@ -24,6 +24,7 @@ const Info = ({ datasetId }: { datasetId: string }) => {
|
||||
const { getValues, setValue, register, handleSubmit } = useForm<DatasetItemType>({
|
||||
defaultValues: datasetDetail
|
||||
});
|
||||
const { datasetModelList, vectorModelList } = useSystemStore();
|
||||
|
||||
const router = useRouter();
|
||||
|
||||
@@ -133,7 +134,7 @@ const Info = ({ datasetId }: { datasetId: string }) => {
|
||||
</Box>
|
||||
<Box flex={[1, '0 0 300px']}>{getValues('vectorModel').maxToken}</Box>
|
||||
</Flex>
|
||||
{qaModelList.length > 1 && (
|
||||
{datasetModelList.length > 1 && (
|
||||
<Flex mt={6} alignItems={'center'}>
|
||||
<Box flex={['0 0 90px', '0 0 160px']} w={0}>
|
||||
{t('core.ai.model.Dataset Agent Model')}
|
||||
@@ -142,12 +143,12 @@ const Info = ({ datasetId }: { datasetId: string }) => {
|
||||
<MySelect
|
||||
w={'100%'}
|
||||
value={getValues('agentModel').model}
|
||||
list={qaModelList.map((item) => ({
|
||||
list={datasetModelList.map((item) => ({
|
||||
label: item.name,
|
||||
value: item.model
|
||||
}))}
|
||||
onchange={(e) => {
|
||||
const agentModel = qaModelList.find((item) => item.model === e);
|
||||
const agentModel = datasetModelList.find((item) => item.model === e);
|
||||
if (!agentModel) return;
|
||||
setValue('agentModel', agentModel);
|
||||
setRefresh((state) => !state);
|
||||
|
||||
@@ -8,7 +8,7 @@ import {
|
||||
getDatasetCollectionById,
|
||||
getDatasetDataItemById
|
||||
} from '@/web/core/dataset/api';
|
||||
import { useToast } from '@/web/common/hooks/useToast';
|
||||
import { useToast } from '@fastgpt/web/hooks/useToast';
|
||||
import MyIcon from '@fastgpt/web/components/common/Icon';
|
||||
import MyModal from '@/components/MyModal';
|
||||
import MyTooltip from '@/components/MyTooltip';
|
||||
@@ -19,7 +19,6 @@ import { useRequest } from '@/web/common/hooks/useRequest';
|
||||
import { countPromptTokens } from '@fastgpt/global/common/string/tiktoken';
|
||||
import { useConfirm } from '@/web/common/hooks/useConfirm';
|
||||
import { getDefaultIndex } from '@fastgpt/global/core/dataset/utils';
|
||||
import { vectorModelList } from '@/web/common/system/staticData';
|
||||
import { DatasetDataIndexTypeEnum } from '@fastgpt/global/core/dataset/constants';
|
||||
import { DatasetDataIndexItemType } from '@fastgpt/global/core/dataset/type';
|
||||
import SideTabs from '@/components/SideTabs';
|
||||
@@ -66,6 +65,7 @@ const InputDataModal = ({
|
||||
const theme = useTheme();
|
||||
const { toast } = useToast();
|
||||
const [currentTab, setCurrentTab] = useState(TabEnum.content);
|
||||
const { vectorModelList } = useSystemStore();
|
||||
|
||||
const { register, handleSubmit, reset, control } = useForm<InputDataType>();
|
||||
const {
|
||||
@@ -139,7 +139,7 @@ const InputDataModal = ({
|
||||
vectorModelList[0];
|
||||
|
||||
return vectorModel?.maxToken || 3000;
|
||||
}, [collection.datasetId.vectorModel]);
|
||||
}, [collection.datasetId.vectorModel, vectorModelList]);
|
||||
|
||||
// import new data
|
||||
const { mutate: sureImportData, isLoading: isImporting } = useRequest({
|
||||
|
||||
@@ -21,7 +21,7 @@ import MyIcon from '@fastgpt/web/components/common/Icon';
|
||||
import { useRequest } from '@/web/common/hooks/useRequest';
|
||||
import { formatTimeToChatTime } from '@/utils/tools';
|
||||
import { getErrText } from '@fastgpt/global/common/error/utils';
|
||||
import { useToast } from '@/web/common/hooks/useToast';
|
||||
import { useToast } from '@fastgpt/web/hooks/useToast';
|
||||
import { customAlphabet } from 'nanoid';
|
||||
import MyTooltip from '@/components/MyTooltip';
|
||||
import { QuestionOutlineIcon } from '@chakra-ui/icons';
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React, { useCallback, useMemo } from 'react';
|
||||
import { useRouter } from 'next/router';
|
||||
import { Box, Flex, IconButton, useTheme, Progress } from '@chakra-ui/react';
|
||||
import { useToast } from '@/web/common/hooks/useToast';
|
||||
import { useToast } from '@fastgpt/web/hooks/useToast';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { getErrText } from '@fastgpt/global/common/error/utils';
|
||||
import { useSystemStore } from '@/web/common/system/useSystemStore';
|
||||
|
||||
@@ -4,7 +4,7 @@ import { useSelectFile } from '@/web/common/file/hooks/useSelectFile';
|
||||
import { useForm } from 'react-hook-form';
|
||||
import { compressImgFileAndUpload } from '@/web/common/file/controller';
|
||||
import { getErrText } from '@fastgpt/global/common/error/utils';
|
||||
import { useToast } from '@/web/common/hooks/useToast';
|
||||
import { useToast } from '@fastgpt/web/hooks/useToast';
|
||||
import { useRouter } from 'next/router';
|
||||
import { useSystemStore } from '@/web/common/system/useSystemStore';
|
||||
import { useRequest } from '@/web/common/hooks/useRequest';
|
||||
@@ -14,19 +14,21 @@ import MyModal from '@/components/MyModal';
|
||||
import { postCreateDataset } from '@/web/core/dataset/api';
|
||||
import type { CreateDatasetParams } from '@/global/core/dataset/api.d';
|
||||
import MySelect from '@/components/Select';
|
||||
import { vectorModelList, qaModelList } from '@/web/common/system/staticData';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import MyRadio from '@/components/common/MyRadio';
|
||||
import { DatasetTypeEnum } from '@fastgpt/global/core/dataset/constants';
|
||||
import { feConfigs } from '@/web/common/system/staticData';
|
||||
import { MongoImageTypeEnum } from '@fastgpt/global/common/file/image/constants';
|
||||
import { QuestionOutlineIcon } from '@chakra-ui/icons';
|
||||
|
||||
const CreateModal = ({ onClose, parentId }: { onClose: () => void; parentId?: string }) => {
|
||||
const { t } = useTranslation();
|
||||
const [refresh, setRefresh] = useState(false);
|
||||
const { toast } = useToast();
|
||||
const router = useRouter();
|
||||
const { isPc } = useSystemStore();
|
||||
const { isPc, feConfigs, vectorModelList, datasetModelList } = useSystemStore();
|
||||
|
||||
const filterNotHiddenVectorModelList = vectorModelList.filter((item) => !item.hidden);
|
||||
|
||||
const { register, setValue, getValues, handleSubmit } = useForm<CreateDatasetParams>({
|
||||
defaultValues: {
|
||||
parentId,
|
||||
@@ -34,8 +36,8 @@ const CreateModal = ({ onClose, parentId }: { onClose: () => void; parentId?: st
|
||||
avatar: '/icon/logo.svg',
|
||||
name: '',
|
||||
intro: '',
|
||||
vectorModel: vectorModelList[0].model,
|
||||
agentModel: qaModelList[0].model
|
||||
vectorModel: filterNotHiddenVectorModelList[0].model,
|
||||
agentModel: datasetModelList[0].model
|
||||
}
|
||||
});
|
||||
|
||||
@@ -145,18 +147,25 @@ const CreateModal = ({ onClose, parentId }: { onClose: () => void; parentId?: st
|
||||
bg={'myWhite.600'}
|
||||
placeholder={t('common.Name')}
|
||||
maxLength={30}
|
||||
{...register('name')}
|
||||
{...register('name', {
|
||||
required: true
|
||||
})}
|
||||
/>
|
||||
</Flex>
|
||||
</Box>
|
||||
{vectorModelList.length > 1 && (
|
||||
{filterNotHiddenVectorModelList.length > 1 && (
|
||||
<Flex mt={6} alignItems={'center'}>
|
||||
<Box flex={'0 0 100px'}>{t('core.ai.model.Vector Model')}</Box>
|
||||
<Flex alignItems={'center'} flex={'0 0 100px'}>
|
||||
{t('core.ai.model.Vector Model')}
|
||||
<MyTooltip label={t('core.dataset.embedding model tip')}>
|
||||
<QuestionOutlineIcon ml={1} />
|
||||
</MyTooltip>
|
||||
</Flex>
|
||||
<Box flex={1}>
|
||||
<MySelect
|
||||
w={'100%'}
|
||||
value={getValues('vectorModel')}
|
||||
list={vectorModelList.map((item) => ({
|
||||
list={filterNotHiddenVectorModelList.map((item) => ({
|
||||
label: item.name,
|
||||
value: item.model
|
||||
}))}
|
||||
@@ -168,14 +177,14 @@ const CreateModal = ({ onClose, parentId }: { onClose: () => void; parentId?: st
|
||||
</Box>
|
||||
</Flex>
|
||||
)}
|
||||
{qaModelList.length > 1 && (
|
||||
{datasetModelList.length > 1 && (
|
||||
<Flex mt={6} alignItems={'center'}>
|
||||
<Box flex={'0 0 100px'}>{t('core.ai.model.Dataset Agent Model')}</Box>
|
||||
<Box flex={1}>
|
||||
<MySelect
|
||||
w={'100%'}
|
||||
value={getValues('agentModel')}
|
||||
list={qaModelList.map((item) => ({
|
||||
list={datasetModelList.map((item) => ({
|
||||
label: item.name,
|
||||
value: item.model
|
||||
}))}
|
||||
|
||||
@@ -46,7 +46,7 @@ import { PermissionTypeEnum } from '@fastgpt/global/support/permission/constant'
|
||||
import { DatasetItemType } from '@fastgpt/global/core/dataset/type';
|
||||
import ParentPaths from '@/components/common/ParentPaths';
|
||||
import DatasetTypeTag from '@/components/core/dataset/DatasetTypeTag';
|
||||
import { useToast } from '@/web/common/hooks/useToast';
|
||||
import { useToast } from '@fastgpt/web/hooks/useToast';
|
||||
import { getErrText } from '@fastgpt/global/common/error/utils';
|
||||
|
||||
const CreateModal = dynamic(() => import('./component/CreateModal'), { ssr: false });
|
||||
@@ -174,21 +174,19 @@ const Kb = () => {
|
||||
{/* create icon */}
|
||||
{userInfo?.team?.canWrite && (
|
||||
<MyMenu
|
||||
offset={[-30, 10]}
|
||||
offset={[-30, 5]}
|
||||
width={120}
|
||||
Button={
|
||||
<Button variant={'primaryOutline'} px={0}>
|
||||
<MenuButton h={'100%'}>
|
||||
<Flex alignItems={'center'} px={'20px'}>
|
||||
<AddIcon mr={2} />
|
||||
<Box>{t('common.Create New')}</Box>
|
||||
</Flex>
|
||||
</MenuButton>
|
||||
<Flex alignItems={'center'} px={'20px'}>
|
||||
<AddIcon mr={2} />
|
||||
<Box>{t('common.Create New')}</Box>
|
||||
</Flex>
|
||||
</Button>
|
||||
}
|
||||
menuList={[
|
||||
{
|
||||
child: (
|
||||
label: (
|
||||
<Flex>
|
||||
<MyIcon name={FolderIcon} w={'20px'} mr={1} />
|
||||
{t('Folder')}
|
||||
@@ -197,7 +195,7 @@ const Kb = () => {
|
||||
onClick: () => setEditFolderData({})
|
||||
},
|
||||
{
|
||||
child: (
|
||||
label: (
|
||||
<Flex>
|
||||
<Image src={'/imgs/module/db.png'} alt={''} w={'20px'} mr={1} />
|
||||
{t('core.dataset.Dataset')}
|
||||
@@ -283,126 +281,129 @@ const Kb = () => {
|
||||
}}
|
||||
>
|
||||
{userInfo?.team.canWrite && dataset.isOwner && (
|
||||
<MyMenu
|
||||
offset={[-30, 10]}
|
||||
width={120}
|
||||
Button={
|
||||
<MenuButton
|
||||
position={'absolute'}
|
||||
top={3}
|
||||
right={3}
|
||||
w={'22px'}
|
||||
h={'22px'}
|
||||
borderRadius={'md'}
|
||||
_hover={{
|
||||
color: 'primary.500',
|
||||
'& .icon': {
|
||||
bg: 'myGray.100'
|
||||
}
|
||||
}}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
}}
|
||||
>
|
||||
<MyIcon
|
||||
className="icon"
|
||||
name={'more'}
|
||||
h={'16px'}
|
||||
w={'16px'}
|
||||
px={1}
|
||||
py={1}
|
||||
borderRadius={'md'}
|
||||
cursor={'pointer'}
|
||||
/>
|
||||
</MenuButton>
|
||||
}
|
||||
menuList={[
|
||||
...(dataset.permission === PermissionTypeEnum.private
|
||||
? [
|
||||
{
|
||||
child: (
|
||||
<Flex alignItems={'center'}>
|
||||
<MyIcon name={'support/permission/publicLight'} w={'14px'} mr={2} />
|
||||
{t('permission.Set Public')}
|
||||
</Flex>
|
||||
),
|
||||
onClick: () => {
|
||||
updateDataset({
|
||||
id: dataset._id,
|
||||
permission: PermissionTypeEnum.public
|
||||
});
|
||||
}
|
||||
}
|
||||
]
|
||||
: [
|
||||
{
|
||||
child: (
|
||||
<Flex alignItems={'center'}>
|
||||
<MyIcon name={'support/permission/privateLight'} w={'14px'} mr={2} />
|
||||
{t('permission.Set Private')}
|
||||
</Flex>
|
||||
),
|
||||
onClick: () => {
|
||||
updateDataset({
|
||||
id: dataset._id,
|
||||
permission: PermissionTypeEnum.private
|
||||
});
|
||||
}
|
||||
}
|
||||
]),
|
||||
{
|
||||
child: (
|
||||
<Flex alignItems={'center'}>
|
||||
<MyIcon name={'edit'} w={'14px'} mr={2} />
|
||||
{t('Rename')}
|
||||
</Flex>
|
||||
),
|
||||
onClick: () =>
|
||||
onOpenTitleModal({
|
||||
defaultVal: dataset.name,
|
||||
onSuccess: (val) => {
|
||||
if (val === dataset.name || !val) return;
|
||||
updateDataset({ id: dataset._id, name: val });
|
||||
}
|
||||
})
|
||||
},
|
||||
{
|
||||
child: (
|
||||
<Flex alignItems={'center'}>
|
||||
<MyIcon name={'common/file/move'} w={'14px'} mr={2} />
|
||||
{t('Move')}
|
||||
</Flex>
|
||||
),
|
||||
onClick: () => setMoveDataId(dataset._id)
|
||||
},
|
||||
{
|
||||
child: (
|
||||
<Flex alignItems={'center'}>
|
||||
<MyIcon name={'export'} w={'14px'} mr={2} />
|
||||
{t('Export')}
|
||||
</Flex>
|
||||
),
|
||||
onClick: () => {
|
||||
exportDataset(dataset);
|
||||
}
|
||||
},
|
||||
{
|
||||
child: (
|
||||
<Flex alignItems={'center'}>
|
||||
<MyIcon name={'delete'} w={'14px'} mr={2} />
|
||||
{t('common.Delete')}
|
||||
</Flex>
|
||||
),
|
||||
onClick: () => {
|
||||
openConfirm(
|
||||
() => onclickDelDataset(dataset._id),
|
||||
undefined,
|
||||
DeleteTipsMap.current[dataset.type]
|
||||
)();
|
||||
}
|
||||
<Box
|
||||
position={'absolute'}
|
||||
top={3}
|
||||
right={3}
|
||||
borderRadius={'md'}
|
||||
_hover={{
|
||||
color: 'primary.500',
|
||||
'& .icon': {
|
||||
bg: 'myGray.100'
|
||||
}
|
||||
]}
|
||||
/>
|
||||
}}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
}}
|
||||
>
|
||||
<MyMenu
|
||||
width={120}
|
||||
Button={
|
||||
<Box w={'22px'} h={'22px'}>
|
||||
<MyIcon
|
||||
className="icon"
|
||||
name={'more'}
|
||||
h={'16px'}
|
||||
w={'16px'}
|
||||
px={1}
|
||||
py={1}
|
||||
borderRadius={'md'}
|
||||
cursor={'pointer'}
|
||||
/>
|
||||
</Box>
|
||||
}
|
||||
menuList={[
|
||||
...(dataset.permission === PermissionTypeEnum.private
|
||||
? [
|
||||
{
|
||||
label: (
|
||||
<Flex alignItems={'center'}>
|
||||
<MyIcon name={'support/permission/publicLight'} w={'14px'} mr={2} />
|
||||
{t('permission.Set Public')}
|
||||
</Flex>
|
||||
),
|
||||
onClick: () => {
|
||||
updateDataset({
|
||||
id: dataset._id,
|
||||
permission: PermissionTypeEnum.public
|
||||
});
|
||||
}
|
||||
}
|
||||
]
|
||||
: [
|
||||
{
|
||||
label: (
|
||||
<Flex alignItems={'center'}>
|
||||
<MyIcon
|
||||
name={'support/permission/privateLight'}
|
||||
w={'14px'}
|
||||
mr={2}
|
||||
/>
|
||||
{t('permission.Set Private')}
|
||||
</Flex>
|
||||
),
|
||||
onClick: () => {
|
||||
updateDataset({
|
||||
id: dataset._id,
|
||||
permission: PermissionTypeEnum.private
|
||||
});
|
||||
}
|
||||
}
|
||||
]),
|
||||
{
|
||||
label: (
|
||||
<Flex alignItems={'center'}>
|
||||
<MyIcon name={'edit'} w={'14px'} mr={2} />
|
||||
{t('Rename')}
|
||||
</Flex>
|
||||
),
|
||||
onClick: () =>
|
||||
onOpenTitleModal({
|
||||
defaultVal: dataset.name,
|
||||
onSuccess: (val) => {
|
||||
if (val === dataset.name || !val) return;
|
||||
updateDataset({ id: dataset._id, name: val });
|
||||
}
|
||||
})
|
||||
},
|
||||
{
|
||||
label: (
|
||||
<Flex alignItems={'center'}>
|
||||
<MyIcon name={'common/file/move'} w={'14px'} mr={2} />
|
||||
{t('Move')}
|
||||
</Flex>
|
||||
),
|
||||
onClick: () => setMoveDataId(dataset._id)
|
||||
},
|
||||
{
|
||||
label: (
|
||||
<Flex alignItems={'center'}>
|
||||
<MyIcon name={'export'} w={'14px'} mr={2} />
|
||||
{t('Export')}
|
||||
</Flex>
|
||||
),
|
||||
onClick: () => {
|
||||
exportDataset(dataset);
|
||||
}
|
||||
},
|
||||
{
|
||||
label: (
|
||||
<Flex alignItems={'center'}>
|
||||
<MyIcon name={'delete'} w={'14px'} mr={2} />
|
||||
{t('common.Delete')}
|
||||
</Flex>
|
||||
),
|
||||
onClick: () => {
|
||||
openConfirm(
|
||||
() => onclickDelDataset(dataset._id),
|
||||
undefined,
|
||||
DeleteTipsMap.current[dataset.type]
|
||||
)();
|
||||
}
|
||||
}
|
||||
]}
|
||||
/>
|
||||
</Box>
|
||||
)}
|
||||
<Flex alignItems={'center'} h={'38px'}>
|
||||
<Avatar src={dataset.avatar} borderRadius={'md'} w={'28px'} />
|
||||
|
||||
21
projects/app/src/pages/index.tsx
Normal file
21
projects/app/src/pages/index.tsx
Normal file
@@ -0,0 +1,21 @@
|
||||
import { serviceSideProps } from '@/web/common/utils/i18n';
|
||||
import React, { useEffect } from 'react';
|
||||
import Loading from '@/components/Loading';
|
||||
import { useRouter } from 'next/router';
|
||||
|
||||
const index = () => {
|
||||
const router = useRouter();
|
||||
useEffect(() => {
|
||||
router.push('/app/list');
|
||||
}, [router]);
|
||||
return <Loading></Loading>;
|
||||
};
|
||||
|
||||
export async function getServerSideProps(content: any) {
|
||||
return {
|
||||
props: {
|
||||
...(await serviceSideProps(content))
|
||||
}
|
||||
};
|
||||
}
|
||||
export default index;
|
||||
@@ -5,8 +5,8 @@ import { PageTypeEnum } from '@/constants/user';
|
||||
import { postFindPassword } from '@/web/support/user/api';
|
||||
import { useSendCode } from '@/web/support/user/hooks/useSendCode';
|
||||
import type { ResLogin } from '@/global/support/api/userRes.d';
|
||||
import { useToast } from '@/web/common/hooks/useToast';
|
||||
import { feConfigs } from '@/web/common/system/staticData';
|
||||
import { useToast } from '@fastgpt/web/hooks/useToast';
|
||||
import { useSystemStore } from '@/web/common/system/useSystemStore';
|
||||
|
||||
interface Props {
|
||||
setPageType: Dispatch<`${PageTypeEnum}`>;
|
||||
@@ -22,6 +22,7 @@ interface RegisterType {
|
||||
|
||||
const RegisterForm = ({ setPageType, loginSuccess }: Props) => {
|
||||
const { toast } = useToast();
|
||||
const { feConfigs } = useSystemStore();
|
||||
const {
|
||||
register,
|
||||
handleSubmit,
|
||||
|
||||
@@ -16,8 +16,7 @@ import { PageTypeEnum } from '@/constants/user';
|
||||
import { OAuthEnum } from '@fastgpt/global/support/user/constant';
|
||||
import { postLogin } from '@/web/support/user/api';
|
||||
import type { ResLogin } from '@/global/support/api/userRes';
|
||||
import { useToast } from '@/web/common/hooks/useToast';
|
||||
import { feConfigs } from '@/web/common/system/staticData';
|
||||
import { useToast } from '@fastgpt/web/hooks/useToast';
|
||||
import { useSystemStore } from '@/web/common/system/useSystemStore';
|
||||
import MyIcon from '@fastgpt/web/components/common/Icon';
|
||||
import { customAlphabet } from 'nanoid';
|
||||
@@ -43,7 +42,7 @@ const LoginForm = ({ setPageType, loginSuccess }: Props) => {
|
||||
const theme = useTheme();
|
||||
const { lastRoute = '/app/list' } = router.query as { lastRoute: string };
|
||||
const { toast } = useToast();
|
||||
const { setLoginStore } = useSystemStore();
|
||||
const { setLoginStore, feConfigs } = useSystemStore();
|
||||
const {
|
||||
register,
|
||||
handleSubmit,
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
import React, { useState, Dispatch, useCallback } from 'react';
|
||||
import { FormControl, Box, Input, Button, FormErrorMessage, Flex } from '@chakra-ui/react';
|
||||
import { FormControl, Box, Input, Button } from '@chakra-ui/react';
|
||||
import { useForm } from 'react-hook-form';
|
||||
import { PageTypeEnum } from '@/constants/user';
|
||||
import { postRegister } from '@/web/support/user/api';
|
||||
import { useSendCode } from '@/web/support/user/hooks/useSendCode';
|
||||
import type { ResLogin } from '@/global/support/api/userRes';
|
||||
import { useToast } from '@/web/common/hooks/useToast';
|
||||
import { useToast } from '@fastgpt/web/hooks/useToast';
|
||||
import { postCreateApp } from '@/web/core/app/api';
|
||||
import { appTemplates } from '@/web/core/app/templates';
|
||||
import { feConfigs } from '@/web/common/system/staticData';
|
||||
import { useSystemStore } from '@/web/common/system/useSystemStore';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
|
||||
interface Props {
|
||||
loginSuccess: (e: ResLogin) => void;
|
||||
@@ -24,6 +25,8 @@ interface RegisterType {
|
||||
|
||||
const RegisterForm = ({ setPageType, loginSuccess }: Props) => {
|
||||
const { toast } = useToast();
|
||||
const { t } = useTranslation();
|
||||
const { feConfigs } = useSystemStore();
|
||||
const {
|
||||
register,
|
||||
handleSubmit,
|
||||
@@ -68,7 +71,7 @@ const RegisterForm = ({ setPageType, loginSuccess }: Props) => {
|
||||
appTemplates.forEach((template) => {
|
||||
postCreateApp({
|
||||
avatar: template.avatar,
|
||||
name: template.name,
|
||||
name: t(template.name),
|
||||
modules: template.modules,
|
||||
type: template.type
|
||||
});
|
||||
|
||||
@@ -6,7 +6,7 @@ import { useChatStore } from '@/web/core/chat/storeChat';
|
||||
import { useUserStore } from '@/web/support/user/useUserStore';
|
||||
import { clearToken, setToken } from '@/web/support/user/auth';
|
||||
import { postFastLogin } from '@/web/support/user/api';
|
||||
import { useToast } from '@/web/common/hooks/useToast';
|
||||
import { useToast } from '@fastgpt/web/hooks/useToast';
|
||||
import Loading from '@/components/Loading';
|
||||
import { serviceSideProps } from '@/web/common/utils/i18n';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
|
||||
@@ -10,7 +10,6 @@ import LoginForm from './components/LoginForm';
|
||||
import dynamic from 'next/dynamic';
|
||||
import { serviceSideProps } from '@/web/common/utils/i18n';
|
||||
import { clearToken, setToken } from '@/web/support/user/auth';
|
||||
import { feConfigs } from '@/web/common/system/staticData';
|
||||
import CommunityModal from '@/components/CommunityModal';
|
||||
import Script from 'next/script';
|
||||
const RegisterForm = dynamic(() => import('./components/RegisterForm'));
|
||||
@@ -19,7 +18,7 @@ const ForgetPasswordForm = dynamic(() => import('./components/ForgetPasswordForm
|
||||
const Login = () => {
|
||||
const router = useRouter();
|
||||
const { lastRoute = '' } = router.query as { lastRoute: string };
|
||||
const { isPc } = useSystemStore();
|
||||
const { feConfigs } = useSystemStore();
|
||||
const [pageType, setPageType] = useState<`${PageTypeEnum}`>(PageTypeEnum.login);
|
||||
const { setUserInfo } = useUserStore();
|
||||
const { setLastChatId, setLastChatAppId } = useChatStore();
|
||||
|
||||
@@ -6,7 +6,7 @@ import { useChatStore } from '@/web/core/chat/storeChat';
|
||||
import { useUserStore } from '@/web/support/user/useUserStore';
|
||||
import { clearToken, setToken } from '@/web/support/user/auth';
|
||||
import { oauthLogin } from '@/web/support/user/api';
|
||||
import { useToast } from '@/web/common/hooks/useToast';
|
||||
import { useToast } from '@fastgpt/web/hooks/useToast';
|
||||
import Loading from '@/components/Loading';
|
||||
import { serviceSideProps } from '@/web/common/utils/i18n';
|
||||
import { getErrText } from '@fastgpt/global/common/error/utils';
|
||||
|
||||
@@ -12,7 +12,7 @@ import { filterExportModules, flowNode2Modules } from '@/components/core/module/
|
||||
import { putUpdatePlugin } from '@/web/core/plugin/api';
|
||||
import { FlowNodeTypeEnum } from '@fastgpt/global/core/module/node/constant';
|
||||
import { ModuleItemType } from '@fastgpt/global/core/module/type';
|
||||
import { useToast } from '@/web/common/hooks/useToast';
|
||||
import { useToast } from '@fastgpt/web/hooks/useToast';
|
||||
|
||||
const ImportSettings = dynamic(() => import('@/components/core/module/Flow/ImportSettings'));
|
||||
const PreviewPlugin = dynamic(() => import('./Preview'));
|
||||
|
||||
@@ -9,7 +9,7 @@ import { FlowNodeTypeEnum } from '@fastgpt/global/core/module/node/constant';
|
||||
import { serviceSideProps } from '@/web/common/utils/i18n';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { getOnePlugin } from '@/web/core/plugin/api';
|
||||
import { useToast } from '@/web/common/hooks/useToast';
|
||||
import { useToast } from '@fastgpt/web/hooks/useToast';
|
||||
import Loading from '@/components/Loading';
|
||||
import { getErrText } from '@fastgpt/global/common/error/utils';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
|
||||
@@ -4,7 +4,7 @@ import { useSelectFile } from '@/web/common/file/hooks/useSelectFile';
|
||||
import { useForm } from 'react-hook-form';
|
||||
import { compressImgFileAndUpload } from '@/web/common/file/controller';
|
||||
import { getErrText } from '@fastgpt/global/common/error/utils';
|
||||
import { useToast } from '@/web/common/hooks/useToast';
|
||||
import { useToast } from '@fastgpt/web/hooks/useToast';
|
||||
import { useRouter } from 'next/router';
|
||||
import { useSystemStore } from '@/web/common/system/useSystemStore';
|
||||
import { useRequest } from '@/web/common/hooks/useRequest';
|
||||
|
||||
@@ -12,10 +12,12 @@ import Avatar from '@/components/Avatar';
|
||||
import EditModal, { defaultForm, FormType } from './component/EditModal';
|
||||
import { getUserPlugins } from '@/web/core/plugin/api';
|
||||
import EmptyTip from '@/components/EmptyTip';
|
||||
import { useUserStore } from '@/web/support/user/useUserStore';
|
||||
|
||||
const MyModules = () => {
|
||||
const { t } = useTranslation();
|
||||
const theme = useTheme();
|
||||
const { userInfo } = useUserStore();
|
||||
const router = useRouter();
|
||||
const [editModalData, setEditModalData] = useState<FormType>();
|
||||
|
||||
@@ -37,13 +39,15 @@ const MyModules = () => {
|
||||
{t('plugin.My Plugins')}({t('common.Beta')})
|
||||
</Box>
|
||||
</Flex>
|
||||
<Button
|
||||
leftIcon={<AddIcon />}
|
||||
variant={'primaryOutline'}
|
||||
onClick={() => setEditModalData(defaultForm)}
|
||||
>
|
||||
{t('common.New Create')}
|
||||
</Button>
|
||||
{userInfo?.team?.canWrite && (
|
||||
<Button
|
||||
leftIcon={<AddIcon />}
|
||||
variant={'primaryOutline'}
|
||||
onClick={() => setEditModalData(defaultForm)}
|
||||
>
|
||||
{t('common.New Create')}
|
||||
</Button>
|
||||
)}
|
||||
</Flex>
|
||||
<Grid
|
||||
py={5}
|
||||
|
||||
304
projects/app/src/pages/price/components/ExtraPlan.tsx
Normal file
304
projects/app/src/pages/price/components/ExtraPlan.tsx
Normal file
@@ -0,0 +1,304 @@
|
||||
import {
|
||||
Box,
|
||||
Flex,
|
||||
Grid,
|
||||
NumberDecrementStepper,
|
||||
NumberInput,
|
||||
NumberIncrementStepper,
|
||||
NumberInputField,
|
||||
NumberInputStepper,
|
||||
Button,
|
||||
useDisclosure,
|
||||
ModalBody,
|
||||
ModalFooter
|
||||
} from '@chakra-ui/react';
|
||||
import { TeamSubSchema } from '@fastgpt/global/support/wallet/sub/type';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import React, { useEffect, useMemo, useState } from 'react';
|
||||
import { useSystemStore } from '@/web/common/system/useSystemStore';
|
||||
import MyIcon from '@fastgpt/web/components/common/Icon';
|
||||
import { formatTime2YMDHM } from '@fastgpt/global/common/string/time';
|
||||
import MySelect from '@/components/Select';
|
||||
import {
|
||||
SubStatusEnum,
|
||||
SubTypeEnum,
|
||||
subSelectMap
|
||||
} from '@fastgpt/global/support/wallet/sub/constants';
|
||||
import { useRequest } from '@/web/common/hooks/useRequest';
|
||||
import {
|
||||
posCheckTeamDatasetSizeSub,
|
||||
postUpdateTeamDatasetSizeSub,
|
||||
putTeamDatasetSubStatus
|
||||
} from '@/web/support/wallet/sub/api';
|
||||
import { SubDatasetSizePreviewCheckResponse } from '@fastgpt/global/support/wallet/sub/api.d';
|
||||
import { useRouter } from 'next/router';
|
||||
import { formatStorePrice2Read } from '@fastgpt/global/support/wallet/bill/tools';
|
||||
import { useConfirm } from '@/web/common/hooks/useConfirm';
|
||||
import { useUserStore } from '@/web/support/user/useUserStore';
|
||||
import MyModal from '@/components/MyModal';
|
||||
|
||||
const ExtraPlan = ({ extraDatasetSize }: { extraDatasetSize?: TeamSubSchema }) => {
|
||||
const { t } = useTranslation();
|
||||
const { subPlans } = useSystemStore();
|
||||
const extraDatasetPrice = subPlans?.extraDatasetSize?.price || 0;
|
||||
const [datasetSize, setDatasetSize] = useState(0);
|
||||
const [isRenew, setIsRenew] = useState('false');
|
||||
const router = useRouter();
|
||||
const { userInfo } = useUserStore();
|
||||
|
||||
const [confirmPayExtraDatasetSizeData, setConfirmPayExtraDatasetSizeData] =
|
||||
useState<SubDatasetSizePreviewCheckResponse>();
|
||||
|
||||
useEffect(() => {
|
||||
setDatasetSize((extraDatasetSize?.nextExtraDatasetSize || 0) / 1000);
|
||||
setIsRenew(extraDatasetSize?.status === SubStatusEnum.active ? 'true' : 'false');
|
||||
}, [extraDatasetSize]);
|
||||
|
||||
const { mutate: onUpdateExtraDatasetSizeStatus } = useRequest({
|
||||
mutationFn: (e: 'true' | 'false') => {
|
||||
setIsRenew(e);
|
||||
return putTeamDatasetSubStatus({
|
||||
status: subSelectMap[e],
|
||||
type: SubTypeEnum.extraDatasetSize
|
||||
});
|
||||
},
|
||||
successToast: t('common.Update success'),
|
||||
errorToast: t('common.error.Update error')
|
||||
});
|
||||
|
||||
const { mutate: onClickUpdateExtraDatasetPlan, isLoading: isPayingExtraDatasetSize } = useRequest(
|
||||
{
|
||||
mutationFn: () => postUpdateTeamDatasetSizeSub({ size: datasetSize }),
|
||||
onSuccess() {
|
||||
setTimeout(() => {
|
||||
router.reload();
|
||||
}, 100);
|
||||
},
|
||||
successToast: t('common.Update success'),
|
||||
errorToast: t('common.error.Update error')
|
||||
}
|
||||
);
|
||||
const { mutate: onClickPreviewCheck, isLoading: isFetchingPreviewCheck } = useRequest({
|
||||
mutationFn: () =>
|
||||
posCheckTeamDatasetSizeSub({
|
||||
size: datasetSize
|
||||
}),
|
||||
onSuccess(res: SubDatasetSizePreviewCheckResponse) {
|
||||
if (!res.payForNewSub) {
|
||||
onClickUpdateExtraDatasetPlan('');
|
||||
return;
|
||||
} else {
|
||||
setConfirmPayExtraDatasetSizeData(res);
|
||||
}
|
||||
},
|
||||
errorToast: t('common.error.Update error')
|
||||
});
|
||||
|
||||
return (
|
||||
<Flex
|
||||
mt={['40px', '90px']}
|
||||
flexDirection={'column'}
|
||||
alignItems={'center'}
|
||||
position={'relative'}
|
||||
>
|
||||
<Box fontWeight={'bold'} fontSize={['24px', '36px']}>
|
||||
{t('support.wallet.subscription.Extra plan')}
|
||||
</Box>
|
||||
<Box mt={8} mb={10} color={'myGray.500'} fontSize={'lg'}>
|
||||
{t('support.wallet.subscription.Extra plan tip')}
|
||||
</Box>
|
||||
<Grid mt={8} gridTemplateColumns={['1fr', '1fr']}>
|
||||
<Box
|
||||
bg={'rgba(255, 255, 255, 0.90)'}
|
||||
px={'32px'}
|
||||
py={'24px'}
|
||||
borderRadius={'2xl'}
|
||||
borderWidth={'1px'}
|
||||
borderColor={'myGray.150'}
|
||||
boxShadow={'1.5'}
|
||||
>
|
||||
<Flex w={['100%', '500px']} borderBottomWidth={'1px'} borderBottomColor={'myGray.200'}>
|
||||
<Box flex={'1 0 0'}>
|
||||
<Box fontSize={'xl'} color={'primary.600'}>
|
||||
{t('support.wallet.subscription.Extra dataset size')}
|
||||
</Box>
|
||||
<Box mt={3} fontSize={['32px', '38px']} fontWeight={'bold'}>
|
||||
¥{extraDatasetPrice}/1k组{' '}
|
||||
<Box ml={1} as={'span'} fontSize={'lg'} color={'myGray.600'} fontWeight={'normal'}>
|
||||
/{t('common.month')}
|
||||
</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
<MyIcon
|
||||
transform={'translate(20px,-20px)'}
|
||||
name={'support/pay/extraDatasetsize'}
|
||||
fill={'none'}
|
||||
/>
|
||||
</Flex>
|
||||
<Box>
|
||||
<Flex mt={4}>
|
||||
<Box flex={'0 0 200px'}>
|
||||
{t('support.wallet.subscription.Current dataset store')}:{' '}
|
||||
</Box>
|
||||
<Box fontWeight={'bold'} flex={1}>
|
||||
{extraDatasetSize?.currentExtraDatasetSize || 0}
|
||||
{t('core.dataset.data.unit')}
|
||||
</Box>
|
||||
</Flex>
|
||||
{extraDatasetSize?.nextExtraDatasetSize !== undefined && (
|
||||
<Flex mt={4}>
|
||||
<Box flex={'0 0 200px'}>
|
||||
{t('support.wallet.subscription.Next sub dataset size')}:
|
||||
</Box>
|
||||
<Box fontWeight={'bold'} flex={1}>
|
||||
{extraDatasetSize?.nextExtraDatasetSize || 0}
|
||||
{t('core.dataset.data.unit')}
|
||||
</Box>
|
||||
</Flex>
|
||||
)}
|
||||
{!!extraDatasetSize?.startTime && (
|
||||
<Flex mt={3}>
|
||||
<Box flex={'0 0 200px'}>订阅开始时间: </Box>
|
||||
<Box>{formatTime2YMDHM(extraDatasetSize?.startTime)}</Box>
|
||||
</Flex>
|
||||
)}
|
||||
{!!extraDatasetSize?.expiredTime && (
|
||||
<Flex mt={3}>
|
||||
<Box flex={'0 0 200px'}>订阅到期时间: </Box>
|
||||
<Box>{formatTime2YMDHM(extraDatasetSize?.expiredTime)}</Box>
|
||||
</Flex>
|
||||
)}
|
||||
<Flex mt={3} alignItems={'center'}>
|
||||
<Box flex={'0 0 200px'}>是否自动续费: </Box>
|
||||
<MySelect
|
||||
value={isRenew}
|
||||
size={'sm'}
|
||||
w={'180px'}
|
||||
bg={'myGray.50'}
|
||||
boxShadow={'none'}
|
||||
list={[
|
||||
{ label: '自动续费', value: 'true' },
|
||||
{ label: '不自动续费', value: 'false' }
|
||||
]}
|
||||
onchange={(e) => {
|
||||
if (!extraDatasetSize) return;
|
||||
onUpdateExtraDatasetSizeStatus(e);
|
||||
}}
|
||||
/>
|
||||
</Flex>
|
||||
<Flex mt={4} alignItems={'center'}>
|
||||
<Box flex={'0 0 200px'}>
|
||||
{t('support.wallet.subscription.Update extra dataset size')}
|
||||
</Box>
|
||||
<Flex alignItems={'center'} mt={1} w={'180px'} position={'relative'}>
|
||||
<NumberInput
|
||||
size={'sm'}
|
||||
flex={1}
|
||||
min={0}
|
||||
max={10000}
|
||||
step={1}
|
||||
value={datasetSize}
|
||||
position={'relative'}
|
||||
onChange={(e) => {
|
||||
setDatasetSize(Number(e));
|
||||
}}
|
||||
>
|
||||
<NumberInputField pr={'30px'} value={datasetSize} step={1} min={0} max={10000} />
|
||||
<NumberInputStepper>
|
||||
<NumberIncrementStepper />
|
||||
<NumberDecrementStepper />
|
||||
</NumberInputStepper>
|
||||
</NumberInput>
|
||||
<Box position={'absolute'} right={'20px'} color={'myGray.500'} fontSize={'xs'}>
|
||||
000{t('core.dataset.data.unit')}
|
||||
</Box>
|
||||
</Flex>
|
||||
</Flex>
|
||||
<Button
|
||||
isDisabled={datasetSize * 1000 === extraDatasetSize?.nextExtraDatasetSize}
|
||||
mt={6}
|
||||
w={'100%'}
|
||||
variant={'primaryGhost'}
|
||||
isLoading={isPayingExtraDatasetSize || isFetchingPreviewCheck}
|
||||
onClick={onClickPreviewCheck}
|
||||
>
|
||||
{t('common.change')}
|
||||
</Button>
|
||||
</Box>
|
||||
</Box>
|
||||
</Grid>
|
||||
|
||||
{/* extra dataset size modal */}
|
||||
{!!confirmPayExtraDatasetSizeData && (
|
||||
<MyModal
|
||||
isOpen
|
||||
onClose={() => setConfirmPayExtraDatasetSizeData(undefined)}
|
||||
title={t('support.wallet.Confirm pay')}
|
||||
iconSrc="common/confirm/rightTip"
|
||||
>
|
||||
<ModalBody px={8} py={5}>
|
||||
<Flex>
|
||||
<Box flex={'0 0 120px'} color={'myGray.600'}>
|
||||
当前额外容量
|
||||
</Box>
|
||||
<Box>{extraDatasetSize?.currentExtraDatasetSize || 0}条</Box>
|
||||
</Flex>
|
||||
<Flex mt={4}>
|
||||
<Box flex={'0 0 120px'} color={'myGray.600'}>
|
||||
新的额外容量
|
||||
</Box>
|
||||
<Box>{confirmPayExtraDatasetSizeData.newSubSize}条</Box>
|
||||
</Flex>
|
||||
<Flex mt={4}>
|
||||
<Box flex={'0 0 120px'} color={'myGray.600'}>
|
||||
新套餐价格
|
||||
</Box>
|
||||
<Box>{formatStorePrice2Read(confirmPayExtraDatasetSizeData.newPlanPrice)}元</Box>
|
||||
</Flex>
|
||||
<Flex mt={4}>
|
||||
<Box flex={'0 0 120px'} color={'myGray.600'}>
|
||||
有效时长
|
||||
</Box>
|
||||
<Box>30天</Box>
|
||||
</Flex>
|
||||
|
||||
{/* <Flex>
|
||||
<Box flex={'0 0 120px'}>账号余额:</Box>
|
||||
<Box>{formatStorePrice2Read(userInfo?.team?.balance).toFixed(3)}元</Box>
|
||||
</Flex> */}
|
||||
</ModalBody>
|
||||
<ModalFooter mx={8} px={0} borderTopWidth={'1px'} borderTopColor={'myGray.200'}>
|
||||
<Box color={'myGray.600'}>账号余额:</Box>
|
||||
{confirmPayExtraDatasetSizeData.balanceEnough ? (
|
||||
<>
|
||||
<Box flex={'1 0 0'}>
|
||||
{formatStorePrice2Read(userInfo?.team?.balance).toFixed(2)}元
|
||||
</Box>
|
||||
<Button
|
||||
isLoading={isPayingExtraDatasetSize}
|
||||
onClick={() => onClickUpdateExtraDatasetPlan('')}
|
||||
>
|
||||
支付{formatStorePrice2Read(confirmPayExtraDatasetSizeData.payPrice).toFixed(2)}元
|
||||
</Button>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<Box color={'red.600'} flex={'1 0 0'}>
|
||||
余额不足
|
||||
</Box>
|
||||
<Button
|
||||
isLoading={isPayingExtraDatasetSize}
|
||||
onClick={() => router.push('/account')}
|
||||
>
|
||||
去充值
|
||||
</Button>
|
||||
</>
|
||||
)}
|
||||
</ModalFooter>
|
||||
</MyModal>
|
||||
)}
|
||||
</Flex>
|
||||
);
|
||||
};
|
||||
|
||||
export default React.memo(ExtraPlan);
|
||||
42
projects/app/src/pages/price/components/FAQ.tsx
Normal file
42
projects/app/src/pages/price/components/FAQ.tsx
Normal file
@@ -0,0 +1,42 @@
|
||||
import React from 'react';
|
||||
import { Box, Button, Flex, Grid } from '@chakra-ui/react';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
|
||||
const FAQ = () => {
|
||||
const { t } = useTranslation();
|
||||
const faqs = [{ title: '怎么付费', describe: '2222' }];
|
||||
|
||||
return (
|
||||
<Flex
|
||||
mt={['40px', '90px']}
|
||||
pb={'10vh'}
|
||||
flexDirection={'column'}
|
||||
alignItems={'center'}
|
||||
position={'relative'}
|
||||
>
|
||||
<Box fontWeight={'bold'} fontSize={['24px', '36px']}>
|
||||
{t('support.wallet.subscription.FAQ')}
|
||||
</Box>
|
||||
<Grid mt={4} gridTemplateColumns={['1fr', '1fr 1fr']} gap={4} w={'100%'}>
|
||||
<Box
|
||||
py={2}
|
||||
px={4}
|
||||
borderRadius={'lg'}
|
||||
borderWidth={'1px'}
|
||||
borderColor={'myGray.150'}
|
||||
bg={'rgba(255,255,255,0.9)'}
|
||||
_hover={{
|
||||
borderColor: 'primary.300'
|
||||
}}
|
||||
>
|
||||
<Box fontSize={'lg'} fontWeight={'500'}>
|
||||
怎么付费
|
||||
</Box>
|
||||
<Box color={'myGray.500'}>2222</Box>
|
||||
</Box>
|
||||
</Grid>
|
||||
</Flex>
|
||||
);
|
||||
};
|
||||
|
||||
export default FAQ;
|
||||
122
projects/app/src/pages/price/components/Points.tsx
Normal file
122
projects/app/src/pages/price/components/Points.tsx
Normal file
@@ -0,0 +1,122 @@
|
||||
import React from 'react';
|
||||
import { Box, Flex, Grid } from '@chakra-ui/react';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
|
||||
import { useSystemStore } from '@/web/common/system/useSystemStore';
|
||||
|
||||
const Points = () => {
|
||||
const { t } = useTranslation();
|
||||
const { llmModelList, audioSpeechModelList, vectorModelList, whisperModel } = useSystemStore();
|
||||
|
||||
return (
|
||||
<Flex
|
||||
mt={['40px', '90px']}
|
||||
flexDirection={'column'}
|
||||
alignItems={'center'}
|
||||
position={'relative'}
|
||||
>
|
||||
<Box fontWeight={'bold'} fontSize={['24px', '36px']}>
|
||||
{t('support.wallet.subscription.Ai points')}
|
||||
</Box>
|
||||
<Grid gap={6} mt={['30px', '48px']} w={'100%'}>
|
||||
<Box
|
||||
display={['block', 'flex']}
|
||||
borderRadius={'xl'}
|
||||
borderWidth={'1px'}
|
||||
borderColor={'myGray.150'}
|
||||
bg={'rgba(255,255,255,0.9)'}
|
||||
overflow={'hidden'}
|
||||
>
|
||||
<Box
|
||||
flex={1}
|
||||
borderRightWidth={'1px'}
|
||||
borderRightColor={'myGray.150'}
|
||||
py={4}
|
||||
px={6}
|
||||
fontSize={'lg'}
|
||||
fontWeight={'bold'}
|
||||
>
|
||||
AI语言模型
|
||||
</Box>
|
||||
<Box flex={4} textAlign={'center'}>
|
||||
{llmModelList?.map((item, i) => (
|
||||
<Flex key={item.model} py={4} bg={i % 2 !== 0 ? 'myGray.50' : ''}>
|
||||
<Box flex={'1 0 0'}>{item.name}</Box>
|
||||
<Box flex={'1 0 0'}>5积分 / 1000字符</Box>
|
||||
</Flex>
|
||||
))}
|
||||
</Box>
|
||||
</Box>
|
||||
<Box
|
||||
display={['block', 'flex']}
|
||||
borderRadius={'xl'}
|
||||
borderWidth={'1px'}
|
||||
borderColor={'myGray.150'}
|
||||
bg={'rgba(255,255,255,0.9)'}
|
||||
overflow={'hidden'}
|
||||
>
|
||||
<Box flex={1} borderRightWidth={'1px'} borderRightColor={'myGray.150'} py={4} px={6}>
|
||||
<Box fontSize={'lg'} fontWeight={'bold'}>
|
||||
索引模型
|
||||
</Box>
|
||||
<Box fontSize={'sm'} mt={1} color={'myGray.500'}>
|
||||
文档索引 & 对话索引
|
||||
</Box>
|
||||
</Box>
|
||||
<Box flex={4} textAlign={'center'}>
|
||||
{vectorModelList?.map((item, i) => (
|
||||
<Flex key={item.model} py={4} bg={i % 2 !== 0 ? 'myGray.50' : ''}>
|
||||
<Box flex={'1 0 0'}>{item.name}</Box>
|
||||
<Box flex={'1 0 0'}>5积分 / 1000字符</Box>
|
||||
</Flex>
|
||||
))}
|
||||
</Box>
|
||||
</Box>
|
||||
<Box
|
||||
display={['block', 'flex']}
|
||||
borderRadius={'xl'}
|
||||
borderWidth={'1px'}
|
||||
borderColor={'myGray.150'}
|
||||
bg={'rgba(255,255,255,0.9)'}
|
||||
overflow={'hidden'}
|
||||
>
|
||||
<Box flex={1} borderRightWidth={'1px'} borderRightColor={'myGray.150'} py={4} px={6}>
|
||||
<Box fontSize={'lg'} fontWeight={'bold'}>
|
||||
语音播放
|
||||
</Box>
|
||||
</Box>
|
||||
<Box flex={4} textAlign={'center'}>
|
||||
{audioSpeechModelList?.map((item, i) => (
|
||||
<Flex key={item.model} py={4} bg={i % 2 !== 0 ? 'myGray.50' : ''}>
|
||||
<Box flex={'1 0 0'}>{item.name}</Box>
|
||||
<Box flex={'1 0 0'}>5积分 / 1000字符</Box>
|
||||
</Flex>
|
||||
))}
|
||||
</Box>
|
||||
</Box>
|
||||
<Box
|
||||
display={['block', 'flex']}
|
||||
borderRadius={'xl'}
|
||||
borderWidth={'1px'}
|
||||
borderColor={'myGray.150'}
|
||||
bg={'rgba(255,255,255,0.9)'}
|
||||
overflow={'hidden'}
|
||||
>
|
||||
<Box flex={1} borderRightWidth={'1px'} borderRightColor={'myGray.150'} py={4} px={6}>
|
||||
<Box fontSize={'lg'} fontWeight={'bold'}>
|
||||
语音输入
|
||||
</Box>
|
||||
</Box>
|
||||
<Box flex={4} textAlign={'center'} h={'100%'}>
|
||||
<Flex py={4}>
|
||||
<Box flex={'1 0 0'}>{whisperModel?.name}</Box>
|
||||
<Box flex={'1 0 0'}>{whisperModel?.inputPrice}积分 / 分钟</Box>
|
||||
</Flex>
|
||||
</Box>
|
||||
</Box>
|
||||
</Grid>
|
||||
</Flex>
|
||||
);
|
||||
};
|
||||
|
||||
export default React.memo(Points);
|
||||
340
projects/app/src/pages/price/components/Standard.tsx
Normal file
340
projects/app/src/pages/price/components/Standard.tsx
Normal file
@@ -0,0 +1,340 @@
|
||||
import React, { useMemo, useState } from 'react';
|
||||
import MyIcon from '@fastgpt/web/components/common/Icon';
|
||||
import { Box, Button, Flex, Grid } from '@chakra-ui/react';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import { StandardSubLevelEnum, SubModeEnum } from '@fastgpt/global/support/wallet/sub/constants';
|
||||
import { useUserStore } from '@/web/support/user/useUserStore';
|
||||
import { postCheckStandardSub, postUpdateStandardSub } from '@/web/support/wallet/sub/api';
|
||||
import { useSystemStore } from '@/web/common/system/useSystemStore';
|
||||
import { standardSubLevelMap } from '@fastgpt/global/support/wallet/sub/constants';
|
||||
import { StandardSubPlanParams } from '@fastgpt/global/support/wallet/sub/api';
|
||||
import { useRequest } from '@/web/common/hooks/useRequest';
|
||||
import { StandardSubPlanUpdateResponse } from '@fastgpt/global/support/wallet/sub/api.d';
|
||||
import { useToast } from '@fastgpt/web/hooks/useToast';
|
||||
import { useConfirm } from '@/web/common/hooks/useConfirm';
|
||||
import { formatStorePrice2Read } from '@fastgpt/global/support/wallet/bill/tools';
|
||||
import { TeamSubSchema } from '@fastgpt/global/support/wallet/sub/type';
|
||||
|
||||
const Standard = ({
|
||||
standardPlan,
|
||||
refetchTeamSubPlan
|
||||
}: {
|
||||
standardPlan?: TeamSubSchema;
|
||||
refetchTeamSubPlan: () => void;
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
const { subPlans, feConfigs } = useSystemStore();
|
||||
const { toast } = useToast();
|
||||
const { ConfirmModal, openConfirm } = useConfirm({});
|
||||
|
||||
const [selectSubMode, setSelectSubMode] = useState<`${SubModeEnum}`>(SubModeEnum.month);
|
||||
|
||||
const standardSubList = useMemo(() => {
|
||||
return subPlans?.standard
|
||||
? Object.entries(subPlans.standard).map(([level, value]) => {
|
||||
return {
|
||||
price: value.price * (selectSubMode === SubModeEnum.month ? 1 : 10),
|
||||
level: level as `${StandardSubLevelEnum}`,
|
||||
...standardSubLevelMap[level as `${StandardSubLevelEnum}`],
|
||||
maxTeamMember: value.maxTeamMember,
|
||||
maxAppAmount: value.maxAppAmount,
|
||||
maxDatasetAmount: value.maxDatasetAmount,
|
||||
chatHistoryStoreDuration: value.chatHistoryStoreDuration,
|
||||
maxDatasetSize: value.maxDatasetSize,
|
||||
customApiKey: value.customApiKey,
|
||||
customCopyright: value.customCopyright,
|
||||
trainingWeight: value.trainingWeight,
|
||||
reRankWeight: value.reRankWeight,
|
||||
totalPoints: value.totalPoints * (selectSubMode === SubModeEnum.month ? 1 : 12),
|
||||
websiteSyncInterval: value.websiteSyncInterval
|
||||
};
|
||||
})
|
||||
: [];
|
||||
}, [subPlans?.standard, selectSubMode]);
|
||||
|
||||
const { mutate: onclickUpdateStandardPlan, isLoading: isUpdatingStandardPlan } = useRequest({
|
||||
mutationFn: (data: StandardSubPlanParams) => postUpdateStandardSub(data),
|
||||
onSuccess() {
|
||||
refetchTeamSubPlan();
|
||||
},
|
||||
successToast: t('support.wallet.subscription.Standard update success'),
|
||||
errorToast: t('support.wallet.subscription.Standard update fail')
|
||||
});
|
||||
|
||||
const { mutate: onclickPreCheckStandPlan, isLoading: isCheckingStandardPlan } = useRequest({
|
||||
mutationFn: (data: StandardSubPlanParams) => postCheckStandardSub(data),
|
||||
onSuccess(res: StandardSubPlanUpdateResponse) {
|
||||
if (!res.balanceEnough) {
|
||||
return toast({
|
||||
status: 'warning',
|
||||
title: t('support.wallet.Balance not enough tip')
|
||||
});
|
||||
}
|
||||
if (res.payPrice === undefined) {
|
||||
onclickUpdateStandardPlan({
|
||||
level: res.nextSubLevel,
|
||||
mode: res.nextMode
|
||||
});
|
||||
} else if (res.payPrice > 0) {
|
||||
openConfirm(
|
||||
() =>
|
||||
onclickUpdateStandardPlan({
|
||||
level: res.nextSubLevel,
|
||||
mode: res.nextMode
|
||||
}),
|
||||
undefined,
|
||||
t('support.wallet.subscription.Standard plan pay confirm', {
|
||||
payPrice: formatStorePrice2Read(res.payPrice).toFixed(2)
|
||||
})
|
||||
)();
|
||||
} else {
|
||||
openConfirm(
|
||||
() =>
|
||||
onclickUpdateStandardPlan({
|
||||
level: res.nextSubLevel,
|
||||
mode: res.nextMode
|
||||
}),
|
||||
undefined,
|
||||
t('support.wallet.subscription.Refund plan and pay confirm', {
|
||||
amount: formatStorePrice2Read(Math.abs(res.payPrice)).toFixed(2)
|
||||
})
|
||||
)();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return (
|
||||
<Flex flexDirection={'column'} alignItems={'center'} position={'relative'}>
|
||||
<Box fontWeight={'bold'} fontSize={['24px', '36px']}>
|
||||
{t('support.wallet.subscription.Sub plan')}
|
||||
</Box>
|
||||
<Box mt={8} mb={10} color={'myGray.500'} fontSize={'lg'}>
|
||||
{t('support.wallet.subscription.Sub plan tip')}
|
||||
</Box>
|
||||
<Box>
|
||||
<RowTabs
|
||||
list={[
|
||||
{ label: t('support.wallet.subscription.mode.Month'), value: SubModeEnum.month },
|
||||
{
|
||||
label: (
|
||||
<Flex>
|
||||
{t('support.wallet.subscription.mode.Year')}
|
||||
<Box color={selectSubMode === SubModeEnum.month ? 'red.600' : 'auto'}>
|
||||
({t('support.wallet.subscription.mode.Year sale')})
|
||||
</Box>
|
||||
</Flex>
|
||||
),
|
||||
value: SubModeEnum.year
|
||||
}
|
||||
]}
|
||||
value={selectSubMode}
|
||||
onChange={(e) => setSelectSubMode(e as `${SubModeEnum}`)}
|
||||
/>
|
||||
</Box>
|
||||
{/* card */}
|
||||
<Grid
|
||||
mt={[10, '48px']}
|
||||
gridTemplateColumns={['1fr', 'repeat(2,1fr)', 'repeat(4,1fr)']}
|
||||
gap={[4, 6, 8]}
|
||||
w={'100%'}
|
||||
>
|
||||
{standardSubList.map((item) => (
|
||||
<Box
|
||||
key={item.level}
|
||||
bg={'rgba(255, 255, 255, 0.90)'}
|
||||
p={'28px'}
|
||||
borderRadius={'2xl'}
|
||||
borderWidth={'1px'}
|
||||
borderColor={'myGray.150'}
|
||||
boxShadow={'1.5'}
|
||||
>
|
||||
<Box fontSize={'lg'} fontWeight={'500'}>
|
||||
{t(item.label)}
|
||||
</Box>
|
||||
<Box fontSize={['32px', '42px']} fontWeight={'bold'}>
|
||||
¥{item.price}
|
||||
</Box>
|
||||
<Box color={'myGray.500'} h={'40px'}>
|
||||
{t(item.desc, { title: feConfigs?.systemTitle })}
|
||||
</Box>
|
||||
{(() => {
|
||||
if (item.level === StandardSubLevelEnum.free && selectSubMode === SubModeEnum.year) {
|
||||
return (
|
||||
<Button isDisabled mt={4} mb={6} w={'100%'} variant={'solid'}>
|
||||
{t('support.wallet.subscription.Nonsupport')}
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
if (
|
||||
item.level === standardPlan?.currentSubLevel &&
|
||||
selectSubMode === standardPlan?.currentMode
|
||||
) {
|
||||
return (
|
||||
<Button mt={4} mb={6} w={'100%'} variant={'whiteBase'} isDisabled>
|
||||
{t('support.wallet.subscription.Current plan')}
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
if (
|
||||
item.level === standardPlan?.nextSubLevel &&
|
||||
selectSubMode === standardPlan?.nextMode
|
||||
) {
|
||||
return (
|
||||
<Button mt={4} mb={6} w={'100%'} variant={'whiteBase'} isDisabled>
|
||||
{t('support.wallet.subscription.Next plan')}
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<Button
|
||||
mt={4}
|
||||
mb={6}
|
||||
w={'100%'}
|
||||
variant={'primaryGhost'}
|
||||
isLoading={isUpdatingStandardPlan || isCheckingStandardPlan}
|
||||
onClick={() =>
|
||||
onclickPreCheckStandPlan({
|
||||
level: item.level,
|
||||
mode: selectSubMode
|
||||
})
|
||||
}
|
||||
>
|
||||
{t('support.wallet.subscription.Buy now')}
|
||||
</Button>
|
||||
);
|
||||
})()}
|
||||
|
||||
{/* function list */}
|
||||
<Grid gap={4}>
|
||||
<Flex alignItems={'center'}>
|
||||
<MyIcon name={'price/right'} w={'16px'} mr={3} />
|
||||
<Box color={'myGray.600'}>
|
||||
{t('support.wallet.subscription.function.Max members', {
|
||||
amount: item.maxTeamMember
|
||||
})}
|
||||
</Box>
|
||||
</Flex>
|
||||
<Flex alignItems={'center'}>
|
||||
<MyIcon name={'price/right'} w={'16px'} mr={3} />
|
||||
<Box color={'myGray.600'}>
|
||||
{t('support.wallet.subscription.function.Max app', {
|
||||
amount: item.maxAppAmount
|
||||
})}
|
||||
</Box>
|
||||
</Flex>
|
||||
<Flex alignItems={'center'}>
|
||||
<MyIcon name={'price/right'} w={'16px'} mr={3} />
|
||||
<Box color={'myGray.600'}>
|
||||
{t('support.wallet.subscription.function.Max dataset', {
|
||||
amount: item.maxDatasetAmount
|
||||
})}
|
||||
</Box>
|
||||
</Flex>
|
||||
<Flex alignItems={'center'}>
|
||||
<MyIcon name={'price/right'} w={'16px'} mr={3} />
|
||||
<Box color={'myGray.600'}>
|
||||
{t('support.wallet.subscription.function.History store', {
|
||||
amount: item.chatHistoryStoreDuration
|
||||
})}
|
||||
</Box>
|
||||
</Flex>
|
||||
<Flex alignItems={'center'}>
|
||||
<MyIcon name={'price/right'} w={'16px'} mr={3} />
|
||||
<Box color={'myGray.600'}>
|
||||
{t('support.wallet.subscription.function.Max dataset size', {
|
||||
amount: item.maxDatasetSize
|
||||
})}
|
||||
</Box>
|
||||
</Flex>
|
||||
<Flex alignItems={'center'}>
|
||||
<MyIcon name={'price/right'} w={'16px'} mr={3} />
|
||||
<Box color={'myGray.600'}>
|
||||
{t('support.wallet.subscription.function.Points', {
|
||||
amount: item.totalPoints
|
||||
})}
|
||||
</Box>
|
||||
</Flex>
|
||||
<Flex alignItems={'center'}>
|
||||
<MyIcon name={'price/right'} w={'16px'} mr={3} />
|
||||
<Box color={'myGray.600'}>
|
||||
{t('support.wallet.subscription.Training weight', {
|
||||
weight: item.trainingWeight
|
||||
})}
|
||||
</Box>
|
||||
</Flex>
|
||||
{!!item.customApiKey && (
|
||||
<Flex alignItems={'center'}>
|
||||
<MyIcon name={'price/right'} w={'16px'} mr={3} />
|
||||
<Box color={'myGray.600'}>个人API Key</Box>
|
||||
</Flex>
|
||||
)}
|
||||
{!!item.websiteSyncInterval && (
|
||||
<Flex alignItems={'center'}>
|
||||
<MyIcon name={'price/right'} w={'16px'} mr={3} />
|
||||
<Box color={'myGray.600'}>{item.websiteSyncInterval} h/次 web站点同步</Box>
|
||||
</Flex>
|
||||
)}
|
||||
</Grid>
|
||||
</Box>
|
||||
))}
|
||||
</Grid>
|
||||
|
||||
<ConfirmModal />
|
||||
</Flex>
|
||||
);
|
||||
};
|
||||
|
||||
export default React.memo(Standard);
|
||||
|
||||
const RowTabs = ({
|
||||
list,
|
||||
value,
|
||||
onChange
|
||||
}: {
|
||||
list: {
|
||||
icon?: string;
|
||||
label: string | React.ReactNode;
|
||||
value: string;
|
||||
}[];
|
||||
value: string;
|
||||
onChange: (e: string) => void;
|
||||
}) => {
|
||||
return (
|
||||
<Box
|
||||
display={'inline-flex'}
|
||||
px={'3px'}
|
||||
py={'3px'}
|
||||
borderRadius={'md'}
|
||||
borderWidth={'1px'}
|
||||
borderColor={'primary.300'}
|
||||
bg={'primary.50'}
|
||||
gap={'4px'}
|
||||
>
|
||||
{list.map((item) => (
|
||||
<Flex
|
||||
key={item.value}
|
||||
alignItems={'center'}
|
||||
justifyContent={'center'}
|
||||
cursor={'pointer'}
|
||||
borderRadius={'md'}
|
||||
px={'12px'}
|
||||
py={'7px'}
|
||||
userSelect={'none'}
|
||||
w={['150px', '170px']}
|
||||
{...(value === item.value
|
||||
? {
|
||||
color: 'white',
|
||||
boxShadow: '1.5',
|
||||
bg: 'primary.600'
|
||||
}
|
||||
: {
|
||||
onClick: () => onChange(item.value)
|
||||
})}
|
||||
>
|
||||
{item.icon && <MyIcon name={item.icon as any} mr={1} w={'14px'} />}
|
||||
<Box>{item.label}</Box>
|
||||
</Flex>
|
||||
))}
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
57
projects/app/src/pages/price/index.tsx
Normal file
57
projects/app/src/pages/price/index.tsx
Normal file
@@ -0,0 +1,57 @@
|
||||
import React from 'react';
|
||||
import { serviceSideProps } from '@/web/common/utils/i18n';
|
||||
import { Box, Image } from '@chakra-ui/react';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import { useUserStore } from '@/web/support/user/useUserStore';
|
||||
import { getTeamDatasetValidSub } from '@/web/support/wallet/sub/api';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
|
||||
import StandardPlan from './components/Standard';
|
||||
import ExtraPlan from './components/ExtraPlan';
|
||||
import PointsCard from './components/Points';
|
||||
import FAQ from './components/FAQ';
|
||||
|
||||
const PriceBox = () => {
|
||||
const { t } = useTranslation();
|
||||
const { userInfo } = useUserStore();
|
||||
|
||||
const { data: teamSubPlan, refetch: refetchTeamSubPlan } = useQuery(
|
||||
['getTeamDatasetValidSub'],
|
||||
getTeamDatasetValidSub,
|
||||
{
|
||||
enabled: !!userInfo
|
||||
}
|
||||
);
|
||||
|
||||
return (
|
||||
<Box
|
||||
h={'100%'}
|
||||
overflow={'overlay'}
|
||||
w={'100%'}
|
||||
px={['20px', '5vw']}
|
||||
py={['30px', '80px']}
|
||||
backgroundImage={'url(/imgs/priceBg.svg)'}
|
||||
backgroundSize={'cover'}
|
||||
backgroundRepeat={'no-repeat'}
|
||||
>
|
||||
{/* standard sub */}
|
||||
<StandardPlan standardPlan={teamSubPlan?.standard} refetchTeamSubPlan={refetchTeamSubPlan} />
|
||||
|
||||
<ExtraPlan extraDatasetSize={teamSubPlan?.extraDatasetSize} />
|
||||
|
||||
{/* points */}
|
||||
<PointsCard />
|
||||
|
||||
{/* question */}
|
||||
<FAQ />
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
export default PriceBox;
|
||||
|
||||
export async function getServerSideProps(context: any) {
|
||||
return {
|
||||
props: { ...(await serviceSideProps(context)) }
|
||||
};
|
||||
}
|
||||
@@ -3,7 +3,7 @@ import { Box, Flex } from '@chakra-ui/react';
|
||||
import { ChevronRightIcon } from '@chakra-ui/icons';
|
||||
import MyIcon from '@fastgpt/web/components/common/Icon';
|
||||
import { useRouter } from 'next/router';
|
||||
import { feConfigs } from '@/web/common/system/staticData';
|
||||
import { useSystemStore } from '@/web/common/system/useSystemStore';
|
||||
import { serviceSideProps } from '@/web/common/utils/i18n';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import { getDocPath } from '@/web/common/system/doc';
|
||||
@@ -11,6 +11,7 @@ import { getDocPath } from '@/web/common/system/doc';
|
||||
const Tools = () => {
|
||||
const { t } = useTranslation();
|
||||
const router = useRouter();
|
||||
const { feConfigs } = useSystemStore();
|
||||
const list = [
|
||||
{
|
||||
icon: 'core/dataset/datasetLight',
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import React from 'react';
|
||||
import Price from '@/components/support/wallet/Price';
|
||||
import { useRouter } from 'next/router';
|
||||
import { serviceSideProps } from '@/web/common/utils/i18n';
|
||||
|
||||
const PriceBox = () => {
|
||||
const router = useRouter();
|
||||
@@ -8,3 +9,9 @@ const PriceBox = () => {
|
||||
};
|
||||
|
||||
export default PriceBox;
|
||||
|
||||
export async function getServerSideProps(context: any) {
|
||||
return {
|
||||
props: { ...(await serviceSideProps(context)) }
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user