mirror of
https://github.com/labring/FastGPT.git
synced 2025-08-03 13:38:00 +00:00
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:
@@ -32,7 +32,7 @@ import { useLoading } from '@/web/common/hooks/useLoading';
|
||||
import dayjs from 'dayjs';
|
||||
import { AddIcon, QuestionOutlineIcon } from '@chakra-ui/icons';
|
||||
import { useCopyData } from '@/web/common/hooks/useCopyData';
|
||||
import { feConfigs } from '@/web/common/system/staticData';
|
||||
import { useSystemStore } from '@/web/common/system/useSystemStore';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import MyIcon from '@fastgpt/web/components/common/Icon';
|
||||
import MyModal from '@/components/MyModal';
|
||||
@@ -40,6 +40,7 @@ import { useForm } from 'react-hook-form';
|
||||
import { useRequest } from '@/web/common/hooks/useRequest';
|
||||
import MyTooltip from '@/components/MyTooltip';
|
||||
import { getDocPath } from '@/web/common/system/doc';
|
||||
import MyMenu from '@/components/MyMenu';
|
||||
|
||||
type EditProps = EditApiKeyProps & { _id?: string };
|
||||
const defaultEditData: EditProps = {
|
||||
@@ -54,6 +55,7 @@ const ApiKeyTable = ({ tips, appId }: { tips: string; appId?: string }) => {
|
||||
const { Loading } = useLoading();
|
||||
const theme = useTheme();
|
||||
const { copyData } = useCopyData();
|
||||
const { feConfigs } = useSystemStore();
|
||||
const [baseUrl, setBaseUrl] = useState('https://fastgpt.in/api');
|
||||
const [editData, setEditData] = useState<EditProps>();
|
||||
const [apiKey, setApiKey] = useState('');
|
||||
@@ -177,35 +179,37 @@ const ApiKeyTable = ({ tips, appId }: { tips: string; appId?: string }) => {
|
||||
: t('common.Un used')}
|
||||
</Td>
|
||||
<Td>
|
||||
<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
|
||||
offset={[-50, 5]}
|
||||
Button={
|
||||
<MyIcon
|
||||
name={'more'}
|
||||
w={'14px'}
|
||||
p={2}
|
||||
_hover={{ bg: 'myWhite.600 ' }}
|
||||
cursor={'pointer'}
|
||||
borderRadius={'md'}
|
||||
/>
|
||||
}
|
||||
menuList={[
|
||||
{
|
||||
label: t('common.Edit'),
|
||||
icon: 'edit',
|
||||
onClick: () =>
|
||||
setEditData({
|
||||
_id,
|
||||
name,
|
||||
limit,
|
||||
appId
|
||||
})
|
||||
}
|
||||
py={[2, 3]}
|
||||
>
|
||||
<MyIcon name={'edit'} w={['14px', '16px']} />
|
||||
<Box ml={[1, 2]}>{t('common.Edit')}</Box>
|
||||
</MenuItem>
|
||||
<MenuItem onClick={() => onclickRemove(_id)} py={[2, 3]}>
|
||||
<MyIcon name={'delete'} w={['14px', '16px']} />
|
||||
<Box ml={[1, 2]}>{t('common.Delete')}</Box>
|
||||
</MenuItem>
|
||||
</MenuList>
|
||||
</Menu>
|
||||
},
|
||||
{
|
||||
label: t('common.Delete'),
|
||||
icon: 'delete',
|
||||
onClick: () => onclickRemove(_id)
|
||||
}
|
||||
]}
|
||||
/>
|
||||
</Td>
|
||||
</Tr>
|
||||
))}
|
||||
@@ -285,6 +289,7 @@ function EditKeyModal({
|
||||
}) {
|
||||
const { t } = useTranslation();
|
||||
const isEdit = useMemo(() => !!defaultData._id, [defaultData]);
|
||||
const { feConfigs } = useSystemStore();
|
||||
|
||||
const {
|
||||
register,
|
||||
|
@@ -3,7 +3,7 @@ import { useForm } from 'react-hook-form';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import { useSelectFile } from '@/web/common/file/hooks/useSelectFile';
|
||||
import { compressImgFileAndUpload } from '@/web/common/file/controller';
|
||||
import { useToast } from '@/web/common/hooks/useToast';
|
||||
import { useToast } from '@fastgpt/web/hooks/useToast';
|
||||
import { getErrText } from '@fastgpt/global/common/error/utils';
|
||||
import { useRequest } from '@/web/common/hooks/useRequest';
|
||||
import MyModal from '@/components/MyModal';
|
||||
|
@@ -42,7 +42,7 @@ import { useLoading } from '@/web/common/hooks/useLoading';
|
||||
import { FormDataType, defaultForm } from './EditModal';
|
||||
import MyMenu from '@/components/MyMenu';
|
||||
import { useConfirm } from '@/web/common/hooks/useConfirm';
|
||||
import { useToast } from '@/web/common/hooks/useToast';
|
||||
import { useToast } from '@fastgpt/web/hooks/useToast';
|
||||
|
||||
const EditModal = dynamic(() => import('./EditModal'));
|
||||
const InviteModal = dynamic(() => import('./InviteModal'));
|
||||
@@ -324,11 +324,13 @@ const TeamManageModal = ({ onClose }: { onClose: () => void }) => {
|
||||
item.role !== TeamMemberRoleEnum.owner && (
|
||||
<MyMenu
|
||||
width={20}
|
||||
trigger="click"
|
||||
Button={
|
||||
<MenuButton
|
||||
_hover={{
|
||||
bg: 'myWhite.600'
|
||||
}}
|
||||
borderRadius={'md'}
|
||||
px={2}
|
||||
py={1}
|
||||
lineHeight={1}
|
||||
@@ -344,7 +346,7 @@ const TeamManageModal = ({ onClose }: { onClose: () => void }) => {
|
||||
menuList={[
|
||||
{
|
||||
isActive: item.role === TeamMemberRoleEnum.visitor,
|
||||
child: t('user.team.Invite Role Visitor Tip'),
|
||||
label: t('user.team.Invite Role Visitor Tip'),
|
||||
onClick: () => {
|
||||
onUpdateMember({
|
||||
teamId: item.teamId,
|
||||
@@ -355,7 +357,7 @@ const TeamManageModal = ({ onClose }: { onClose: () => void }) => {
|
||||
},
|
||||
{
|
||||
isActive: item.role === TeamMemberRoleEnum.admin,
|
||||
child: t('user.team.Invite Role Admin Tip'),
|
||||
label: t('user.team.Invite Role Admin Tip'),
|
||||
onClick: () => {
|
||||
onUpdateMember({
|
||||
teamId: item.teamId,
|
||||
@@ -367,7 +369,7 @@ const TeamManageModal = ({ onClose }: { onClose: () => void }) => {
|
||||
...(item.status === TeamMemberStatusEnum.reject
|
||||
? [
|
||||
{
|
||||
child: t('user.team.Reinvite'),
|
||||
label: t('user.team.Reinvite'),
|
||||
onClick: () => {
|
||||
onUpdateMember({
|
||||
teamId: item.teamId,
|
||||
@@ -379,7 +381,7 @@ const TeamManageModal = ({ onClose }: { onClose: () => void }) => {
|
||||
]
|
||||
: []),
|
||||
{
|
||||
child: t('user.team.Remove Member Tip'),
|
||||
label: t('user.team.Remove Member Tip'),
|
||||
onClick: () =>
|
||||
openRemoveMember(
|
||||
() =>
|
||||
|
@@ -4,13 +4,14 @@ import { useUserStore } from '@/web/support/user/useUserStore';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import MyTooltip from '@/components/MyTooltip';
|
||||
import dynamic from 'next/dynamic';
|
||||
import { feConfigs } from '@/web/common/system/staticData';
|
||||
import { useToast } from '@/web/common/hooks/useToast';
|
||||
import { useSystemStore } from '@/web/common/system/useSystemStore';
|
||||
import { useToast } from '@fastgpt/web/hooks/useToast';
|
||||
|
||||
const TeamManageModal = dynamic(() => import('../TeamManageModal'));
|
||||
|
||||
const TeamMenu = () => {
|
||||
const theme = useTheme();
|
||||
const { feConfigs } = useSystemStore();
|
||||
const { t } = useTranslation();
|
||||
const { userInfo } = useUserStore();
|
||||
const { toast } = useToast();
|
||||
|
@@ -15,15 +15,16 @@ import { getTeamList, updateInviteResult } from '@/web/support/user/team/api';
|
||||
import { TeamMemberStatusEnum } from '@fastgpt/global/support/user/team/constant';
|
||||
import Avatar from '@/components/Avatar';
|
||||
import { useRequest } from '@/web/common/hooks/useRequest';
|
||||
import { useToast } from '@/web/common/hooks/useToast';
|
||||
import { useToast } from '@fastgpt/web/hooks/useToast';
|
||||
import { useConfirm } from '@/web/common/hooks/useConfirm';
|
||||
import { feConfigs } from '@/web/common/system/staticData';
|
||||
import { useSystemStore } from '@/web/common/system/useSystemStore';
|
||||
|
||||
const UpdateInviteModal = () => {
|
||||
const { t } = useTranslation();
|
||||
const theme = useTheme();
|
||||
const { toast } = useToast();
|
||||
const { ConfirmModal, openConfirm } = useConfirm({});
|
||||
const { feConfigs } = useSystemStore();
|
||||
|
||||
const { data: inviteList = [], refetch } = useQuery(['getInviteList'], () =>
|
||||
feConfigs.isPlus ? getTeamList(TeamMemberStatusEnum.waiting) : []
|
||||
|
@@ -1,29 +1,21 @@
|
||||
import React from 'react';
|
||||
import { Box, CloseButton } from '@chakra-ui/react';
|
||||
import {
|
||||
chatModelList,
|
||||
vectorModelList,
|
||||
qaModelList,
|
||||
cqModelList,
|
||||
extractModelList,
|
||||
qgModelList,
|
||||
audioSpeechModelList,
|
||||
reRankModelList,
|
||||
whisperModel
|
||||
} from '@/web/common/system/staticData';
|
||||
import { useSystemStore } from '@/web/common/system/useSystemStore';
|
||||
import ReactDOM from 'react-dom';
|
||||
|
||||
import Markdown from '@/components/Markdown';
|
||||
|
||||
const Price = ({ onClose }: { onClose: () => void }) => {
|
||||
const { llmModelList, vectorModelList, audioSpeechModelList, whisperModel } = useSystemStore();
|
||||
|
||||
const list = [
|
||||
{
|
||||
title: '对话模型',
|
||||
title: 'AI语言模型',
|
||||
describe: '',
|
||||
md: `
|
||||
| 模型 | 输入价格(¥) | 输出价格(¥) |
|
||||
| --- | --- | --- |
|
||||
${chatModelList
|
||||
${llmModelList
|
||||
?.map((item) => `| ${item.name} | ${item.inputPrice}/1k tokens | ${item.outputPrice}/1k tokens |`)
|
||||
.join('\n')}`
|
||||
},
|
||||
@@ -36,51 +28,6 @@ ${chatModelList
|
||||
${vectorModelList?.map((item) => `| ${item.name} | ${item.inputPrice}/1k 字符 |`).join('\n')}
|
||||
`
|
||||
},
|
||||
{
|
||||
title: '文件预处理模型(QA 拆分)',
|
||||
describe: '',
|
||||
md: `
|
||||
| 模型 | 价格(¥) |
|
||||
| --- | --- |
|
||||
${qaModelList?.map((item) => `| ${item.name} | ${item.inputPrice}/1k 字符 |`).join('\n')}
|
||||
`
|
||||
},
|
||||
{
|
||||
title: '问题分类',
|
||||
describe: '',
|
||||
md: `
|
||||
| 模型 | 输入价格(¥) | 输出价格(¥) |
|
||||
| --- | --- | --- |
|
||||
${cqModelList
|
||||
?.map(
|
||||
(item) => `| ${item.name} | ${item.inputPrice}/1k tokens | ${item.outputPrice}/1k tokens |`
|
||||
)
|
||||
.join('\n')}`
|
||||
},
|
||||
{
|
||||
title: '内容提取',
|
||||
describe: '',
|
||||
md: `
|
||||
| 模型 | 输入价格(¥) | 输出价格(¥) |
|
||||
| --- | --- | --- |
|
||||
${extractModelList
|
||||
?.map(
|
||||
(item) => `| ${item.name} | ${item.inputPrice}/1k tokens | ${item.outputPrice}/1k tokens |`
|
||||
)
|
||||
.join('\n')}`
|
||||
},
|
||||
{
|
||||
title: '下一步指引',
|
||||
describe: '',
|
||||
md: `
|
||||
| 模型 | 输入价格(¥) | 输出价格(¥) |
|
||||
| --- | --- | --- |
|
||||
${qgModelList
|
||||
?.map(
|
||||
(item) => `| ${item.name} | ${item.inputPrice}/1k tokens | ${item.outputPrice}/1k tokens |`
|
||||
)
|
||||
.join('\n')}`
|
||||
},
|
||||
{
|
||||
title: '语音播放',
|
||||
describe: '',
|
||||
|
@@ -26,8 +26,7 @@ import { QuestionOutlineIcon } from '@chakra-ui/icons';
|
||||
import { useConfirm } from '@/web/common/hooks/useConfirm';
|
||||
import { useRequest } from '@/web/common/hooks/useRequest';
|
||||
import { useRouter } from 'next/router';
|
||||
import { feConfigs } from '@/web/common/system/staticData';
|
||||
import { useToast } from '@/web/common/hooks/useToast';
|
||||
import { useSystemStore } from '@/web/common/system/useSystemStore';
|
||||
import { formatTime2YMDHM } from '@fastgpt/global/common/string/time';
|
||||
import MySelect from '@/components/Select';
|
||||
import {
|
||||
@@ -40,21 +39,20 @@ import { formatStorePrice2Read } from '@fastgpt/global/support/wallet/bill/tools
|
||||
import { useUserStore } from '@/web/support/user/useUserStore';
|
||||
|
||||
const SubDatasetModal = ({ onClose }: { onClose: () => void }) => {
|
||||
const datasetStoreFreeSize = feConfigs?.subscription?.datasetStoreFreeSize || 0;
|
||||
const datasetStorePrice = feConfigs?.subscription?.datasetStorePrice || 0;
|
||||
const { subPlans } = useSystemStore();
|
||||
const datasetStorePrice = subPlans?.extraDatasetSize?.price || 0;
|
||||
|
||||
const { t } = useTranslation();
|
||||
const { toast } = useToast();
|
||||
const router = useRouter();
|
||||
const { ConfirmModal, openConfirm } = useConfirm({});
|
||||
const { userInfo } = useUserStore();
|
||||
const [datasetSize, setDatasetSize] = useState(0);
|
||||
const [isRenew, setIsRenew] = useState('false');
|
||||
|
||||
const { data: datasetSub } = useQuery(['getTeamDatasetValidSub'], getTeamDatasetValidSub, {
|
||||
const { data: teamSubPlan } = useQuery(['getTeamDatasetValidSub'], getTeamDatasetValidSub, {
|
||||
onSuccess(res) {
|
||||
setIsRenew(res?.sub?.status === SubStatusEnum.active ? 'true' : 'false');
|
||||
setDatasetSize((res?.sub?.nextExtraDatasetSize || 0) / 1000);
|
||||
setIsRenew(res?.extraDatasetSize?.status === SubStatusEnum.active ? 'true' : 'false');
|
||||
setDatasetSize((res?.extraDatasetSize?.nextExtraDatasetSize || 0) / 1000);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -88,7 +86,7 @@ const SubDatasetModal = ({ onClose }: { onClose: () => void }) => {
|
||||
<Box>
|
||||
<Flex>
|
||||
<Box flex={'0 0 100px'}>当前额外容量:</Box>
|
||||
<Box>{datasetSub?.sub?.currentExtraDatasetSize || 0}条</Box>
|
||||
<Box>{teamSubPlan?.extraDatasetSize?.currentExtraDatasetSize || 0}条</Box>
|
||||
</Flex>
|
||||
<Flex>
|
||||
<Box flex={'0 0 100px'}>新的额外容量:</Box>
|
||||
@@ -96,7 +94,7 @@ const SubDatasetModal = ({ onClose }: { onClose: () => void }) => {
|
||||
</Flex>
|
||||
<Flex>
|
||||
<Box flex={'0 0 100px'}>新套餐价格:</Box>
|
||||
<Box>{formatStorePrice2Read(res.newPrice)}元</Box>
|
||||
<Box>{formatStorePrice2Read(res.newPlanPrice)}元</Box>
|
||||
</Flex>
|
||||
<Flex>
|
||||
<Box flex={'0 0 100px'}>本次需支付:</Box>
|
||||
@@ -151,7 +149,7 @@ const SubDatasetModal = ({ onClose }: { onClose: () => void }) => {
|
||||
</Flex>
|
||||
<Markdown
|
||||
source={`
|
||||
| 免费知识库 | ${datasetStoreFreeSize}条 |
|
||||
| 套餐知识库容量 | ${teamSubPlan?.standardMaxDatasetSize || Infinity}条 |
|
||||
| --- | --- |
|
||||
| 额外知识库 | ${datasetStorePrice}元/1000条/月 |
|
||||
`}
|
||||
@@ -160,29 +158,29 @@ const SubDatasetModal = ({ onClose }: { onClose: () => void }) => {
|
||||
<Flex mt={4}>
|
||||
<Box flex={'0 0 120px'}>{t('support.wallet.subscription.Current dataset store')}: </Box>
|
||||
<Box ml={2} fontWeight={'bold'} flex={1}>
|
||||
{datasetSub?.sub?.currentExtraDatasetSize || 0}
|
||||
{teamSubPlan?.extraDatasetSize?.currentExtraDatasetSize || 0}
|
||||
{t('core.dataset.data.unit')}
|
||||
</Box>
|
||||
</Flex>
|
||||
{datasetSub?.sub?.nextExtraDatasetSize !== undefined && (
|
||||
{teamSubPlan?.extraDatasetSize?.nextExtraDatasetSize !== undefined && (
|
||||
<Flex mt={4}>
|
||||
<Box flex={'0 0 120px'}>{t('support.wallet.subscription.Next sub dataset size')}: </Box>
|
||||
<Box ml={2} fontWeight={'bold'} flex={1}>
|
||||
{datasetSub?.sub?.nextExtraDatasetSize || 0}
|
||||
{teamSubPlan?.extraDatasetSize?.nextExtraDatasetSize || 0}
|
||||
{t('core.dataset.data.unit')}
|
||||
</Box>
|
||||
</Flex>
|
||||
)}
|
||||
{!!datasetSub?.sub?.startTime && (
|
||||
{!!teamSubPlan?.extraDatasetSize?.startTime && (
|
||||
<Flex mt={3}>
|
||||
<Box flex={'0 0 120px'}>订阅开始时间: </Box>
|
||||
<Box ml={2}>{formatTime2YMDHM(datasetSub?.sub?.startTime)}</Box>
|
||||
<Box ml={2}>{formatTime2YMDHM(teamSubPlan?.extraDatasetSize?.startTime)}</Box>
|
||||
</Flex>
|
||||
)}
|
||||
{!!datasetSub?.sub?.expiredTime && (
|
||||
{!!teamSubPlan?.extraDatasetSize?.expiredTime && (
|
||||
<Flex mt={3}>
|
||||
<Box flex={'0 0 120px'}>订阅到期时间: </Box>
|
||||
<Box ml={2}>{formatTime2YMDHM(datasetSub?.sub?.expiredTime)}</Box>
|
||||
<Box ml={2}>{formatTime2YMDHM(teamSubPlan?.extraDatasetSize?.expiredTime)}</Box>
|
||||
</Flex>
|
||||
)}
|
||||
<Flex mt={3} alignItems={'center'}>
|
||||
@@ -205,7 +203,7 @@ const SubDatasetModal = ({ onClose }: { onClose: () => void }) => {
|
||||
<NumberInput
|
||||
flex={1}
|
||||
min={0}
|
||||
max={1000}
|
||||
max={10000}
|
||||
step={1}
|
||||
value={datasetSize}
|
||||
position={'relative'}
|
||||
@@ -213,7 +211,7 @@ const SubDatasetModal = ({ onClose }: { onClose: () => void }) => {
|
||||
setDatasetSize(Number(e));
|
||||
}}
|
||||
>
|
||||
<NumberInputField value={datasetSize} step={1} min={0} max={1000} />
|
||||
<NumberInputField value={datasetSize} step={1} min={0} max={10000} />
|
||||
<NumberInputStepper>
|
||||
<NumberIncrementStepper />
|
||||
<NumberDecrementStepper />
|
||||
@@ -227,7 +225,7 @@ const SubDatasetModal = ({ onClose }: { onClose: () => void }) => {
|
||||
<Button variant={'whiteBase'} onClick={onClose}>
|
||||
{t('common.Close')}
|
||||
</Button>
|
||||
{datasetSize * 1000 !== datasetSub?.sub?.nextExtraDatasetSize && (
|
||||
{datasetSize * 1000 !== teamSubPlan?.extraDatasetSize?.nextExtraDatasetSize && (
|
||||
<Button ml={3} isLoading={isLoading} onClick={onClickPreviewCheck}>
|
||||
{t('common.Confirm')}
|
||||
</Button>
|
||||
|
Reference in New Issue
Block a user