mirror of
https://github.com/labring/FastGPT.git
synced 2026-03-19 01:00:34 +08:00
V4.14.4 features (#6036)
* feat: add query optimize and bill (#6021) * add query optimize and bill * perf: query extension * fix: embe model * remove log * remove log * fix: test --------- Co-authored-by: xxyyh <2289112474@qq> Co-authored-by: archer <545436317@qq.com> * feat: notice (#6013) * feat: record user's language * feat: notice points/dataset indexes; support count limit; update docker-compose.yml * fix: ts error * feat: send auth code i18n * chore: dataset notice limit * chore: adjust * fix: ts * fix: countLimit race condition; i18n en-prefix locale fallback to en --------- Co-authored-by: archer <545436317@qq.com> * perf: comment * perf: send inform code * fix: type error (#6029) * feat: add ip region for chat logs (#6010) * feat: add ip region for chat logs * refactor: use Geolite2.mmdb * fix: export chat logs * fix: return location directly * test: add unit test * perf: log show ip data * adjust commercial plans (#6008) * plan frontend * plan limit * coupon * discount coupon * fix * type * fix audit * type * plan name * legacy plan * track * feat: add discount coupon * fix * fix discount coupon * openapi * type * type * env * api type * fix * fix: simple agent plugin input & agent dashboard card (#6034) * refactor: remove gridfs (#6031) * fix: replace gridfs multer operations with s3 compatible ops * wip: s3 features * refactor: remove gridfs * fix * perf: mock test * doc * doc * doc * fix: test * fix: s3 * fix: mock s3 * remove invalid config * fix: init query extension * initv4144 (#6037) * chore: initv4144 * fix * version * fix: new plans (#6039) * fix: new plans * qr modal tip * fix: buffer raw text filename (#6040) * fix: initv4144 (#6041) * fix: pay refresh (#6042) * fix: migration shell * rename collection * clear timerlock * clear timerlock * perf: faq * perf: bill schema * fix: openapi * doc * fix: share var render * feat: delete dataset queue * plan usage display (#6043) * plan usage display * text * fix * fix: ts * perf: remove invalid code * perf: init shell * doc * perf: rename field * perf: avatar presign * init * custom plan text (#6045) * fix plans * fix * fixed * computed --------- Co-authored-by: archer <545436317@qq.com> * init shell * plan text & price page back button (#6046) * init * index * delete dataset * delete dataset * perf: delete dataset * init --------- Co-authored-by: YeYuheng <57035043+YYH211@users.noreply.github.com> Co-authored-by: xxyyh <2289112474@qq> Co-authored-by: Finley Ge <32237950+FinleyGe@users.noreply.github.com> Co-authored-by: Roy <whoeverimf5@gmail.com> Co-authored-by: heheer <heheer@sealos.io>
This commit is contained in:
@@ -35,10 +35,6 @@ const Auth = ({ children }: { children: JSX.Element | React.ReactNode }) => {
|
||||
{
|
||||
refetchInterval: 10 * 60 * 1000,
|
||||
onError(error) {
|
||||
console.log('error->', error);
|
||||
router.replace(
|
||||
`/login?lastRoute=${encodeURIComponent(location.pathname + location.search)}`
|
||||
);
|
||||
toast({
|
||||
status: 'warning',
|
||||
title: t('common:support.user.Need to login')
|
||||
|
||||
@@ -2,13 +2,29 @@ import { Box, Flex } from '@chakra-ui/react';
|
||||
import MySelect from '@fastgpt/web/components/common/MySelect';
|
||||
import { useI18nLng } from '@fastgpt/web/hooks/useI18n';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import { useMemo } from 'react';
|
||||
import { useCallback, useMemo } from 'react';
|
||||
import MyIcon from '@fastgpt/web/components/common/Icon';
|
||||
import type { LangEnum } from '@fastgpt/global/common/i18n/type';
|
||||
import { langMap } from '@fastgpt/global/common/i18n/type';
|
||||
import { useUserStore } from '@/web/support/user/useUserStore';
|
||||
|
||||
const I18nLngSelector = () => {
|
||||
const { i18n } = useTranslation();
|
||||
const { onChangeLng } = useI18nLng();
|
||||
const { onChangeLng: onChangeLngI18n } = useI18nLng();
|
||||
const { userInfo, updateUserInfo } = useUserStore();
|
||||
|
||||
const onChangeLng = useCallback(
|
||||
async (lng: `${LangEnum}`) => {
|
||||
if (userInfo?.username) {
|
||||
// logined
|
||||
await updateUserInfo({
|
||||
language: lng
|
||||
});
|
||||
}
|
||||
await onChangeLngI18n(lng);
|
||||
},
|
||||
[userInfo?.username, onChangeLngI18n, updateUserInfo]
|
||||
);
|
||||
|
||||
const list = useMemo(() => {
|
||||
return Object.entries(langMap).map(([key, lang]) => ({
|
||||
|
||||
@@ -122,9 +122,6 @@ const FileSelector = ({
|
||||
Object.entries(fields).forEach(([k, v]) => formData.set(k, v));
|
||||
formData.set('file', file.rawFile);
|
||||
await POST(url, formData, {
|
||||
headers: {
|
||||
'Content-Type': 'multipart/form-data; charset=utf-8'
|
||||
},
|
||||
onUploadProgress: (e) => {
|
||||
if (!e.total) return;
|
||||
const percent = Math.round((e.loaded / e.total) * 100);
|
||||
|
||||
@@ -188,9 +188,6 @@ export const useFileUpload = (props: UseFileUploadOptions) => {
|
||||
Object.entries(fields).forEach(([k, v]) => formData.set(k, v));
|
||||
formData.set('file', copyFile.rawFile);
|
||||
await POST(url, formData, {
|
||||
headers: {
|
||||
'Content-Type': 'multipart/form-data; charset=utf-8'
|
||||
},
|
||||
onUploadProgress: (e) => {
|
||||
if (!e.total) return;
|
||||
const percent = Math.round((e.loaded / e.total) * 100);
|
||||
|
||||
@@ -5,7 +5,7 @@ import {
|
||||
DatasetSearchModeMap
|
||||
} from '@fastgpt/global/core/dataset/constants';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import React, { useMemo } from 'react';
|
||||
import React, { useEffect, useMemo } from 'react';
|
||||
import MyIcon from '@fastgpt/web/components/common/Icon';
|
||||
import { getWebLLMModel } from '@/web/common/system/utils';
|
||||
|
||||
@@ -27,16 +27,15 @@ const SearchParamsTip = ({
|
||||
queryExtensionModel?: string;
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
const { reRankModelList, llmModelList } = useSystemStore();
|
||||
const { reRankModelList } = useSystemStore();
|
||||
|
||||
const hasReRankModel = reRankModelList.length > 0;
|
||||
const hasEmptyResponseMode = responseEmptyText !== undefined;
|
||||
const hasSimilarityMode = usingReRank || searchMode === DatasetSearchModeEnum.embedding;
|
||||
|
||||
const extensionModelName = useMemo(
|
||||
() =>
|
||||
datasetSearchUsingExtensionQuery ? getWebLLMModel(queryExtensionModel)?.name : undefined,
|
||||
[datasetSearchUsingExtensionQuery, queryExtensionModel, llmModelList]
|
||||
() => getWebLLMModel(queryExtensionModel)?.name,
|
||||
[queryExtensionModel]
|
||||
);
|
||||
|
||||
return (
|
||||
|
||||
@@ -11,6 +11,7 @@ import { useUserStore } from '@/web/support/user/useUserStore';
|
||||
import { standardSubLevelMap } from '@fastgpt/global/support/wallet/sub/constants';
|
||||
import { TeamErrEnum } from '@fastgpt/global/common/error/code/team';
|
||||
import { useMount } from 'ahooks';
|
||||
import { useRouter } from 'next/router';
|
||||
|
||||
const NotSufficientModal = () => {
|
||||
const { t } = useTranslation();
|
||||
@@ -62,7 +63,7 @@ const NotSufficientModal = () => {
|
||||
|
||||
export default NotSufficientModal;
|
||||
|
||||
const RechargeModal = ({
|
||||
export const RechargeModal = ({
|
||||
onClose,
|
||||
onPaySuccess
|
||||
}: {
|
||||
@@ -70,7 +71,9 @@ const RechargeModal = ({
|
||||
onPaySuccess: () => void;
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
const router = useRouter();
|
||||
const { teamPlanStatus, initTeamPlanStatus } = useUserStore();
|
||||
const { subPlans } = useSystemStore();
|
||||
|
||||
useMount(() => {
|
||||
initTeamPlanStatus();
|
||||
@@ -78,8 +81,11 @@ const RechargeModal = ({
|
||||
|
||||
const planName = useMemo(() => {
|
||||
if (!teamPlanStatus?.standard?.currentSubLevel) return '';
|
||||
return standardSubLevelMap[teamPlanStatus.standard.currentSubLevel].label;
|
||||
}, [teamPlanStatus?.standard?.currentSubLevel]);
|
||||
return (
|
||||
subPlans?.standard?.[teamPlanStatus.standard.currentSubLevel]?.name ||
|
||||
t(standardSubLevelMap[teamPlanStatus.standard.currentSubLevel]?.label as any)
|
||||
);
|
||||
}, [teamPlanStatus?.standard?.currentSubLevel, subPlans?.standard, t]);
|
||||
|
||||
const [tab, setTab] = useState<'standard' | 'extra'>('standard');
|
||||
|
||||
@@ -96,28 +102,87 @@ const RechargeModal = ({
|
||||
>
|
||||
<ModalBody px={'52px'}>
|
||||
<Flex alignItems={'center'} mb={6}>
|
||||
<FormLabel fontSize={'16px'} fontWeight={'medium'}>
|
||||
{t('common:support.wallet.subscription.Current plan')}
|
||||
</FormLabel>
|
||||
<Box fontSize={'14px'} ml={5} color={'myGray.900'}>
|
||||
{t(planName as any)}
|
||||
</Box>
|
||||
<Flex>
|
||||
<FormLabel fontSize={'16px'} fontWeight={'medium'} color={'myGray.900'}>
|
||||
{t('common:support.wallet.subscription.Current plan')}
|
||||
</FormLabel>
|
||||
<Box fontSize={'14px'} ml={5} color={'myGray.900'}>
|
||||
{t(planName as any)}
|
||||
</Box>
|
||||
</Flex>
|
||||
<Box flex={1} />
|
||||
<Button
|
||||
size={'md'}
|
||||
variant={'transparentBase'}
|
||||
color={'primary.700'}
|
||||
onClick={() => {
|
||||
router.push('/account/usage');
|
||||
onClose();
|
||||
onPaySuccess();
|
||||
}}
|
||||
>
|
||||
{t('common:usage_records')}
|
||||
</Button>
|
||||
</Flex>
|
||||
|
||||
<Flex alignItems={'center'} mb={6}>
|
||||
<FormLabel fontSize={'16px'} fontWeight={'medium'}>
|
||||
{t('common:info.resource')}
|
||||
</FormLabel>
|
||||
<Flex fontSize={'14px'} ml={5} color={'myGray.900'}>
|
||||
<Box>{`${t('common:support.user.team.Dataset usage')}:`}</Box>
|
||||
<Box
|
||||
ml={2}
|
||||
>{`${teamPlanStatus?.usedDatasetIndexSize} / ${teamPlanStatus?.datasetMaxSize || t('account_info:unlimited')}`}</Box>
|
||||
<Box ml={5}>{`${t('common:support.wallet.subscription.AI points usage')}:`}</Box>
|
||||
<Box
|
||||
ml={2}
|
||||
>{`${Math.round(teamPlanStatus?.usedPoints || 0)} / ${teamPlanStatus?.totalPoints || t('account_info:unlimited')}`}</Box>
|
||||
</Flex>
|
||||
<Flex mb={6} gap={8} w={'100%'}>
|
||||
<Box flex={1}>
|
||||
<Flex gap={4} alignItems={'center'} mb={2}>
|
||||
<Box fontSize={'16px'} fontWeight={'medium'} color={'myGray.900'}>
|
||||
{t('common:support.wallet.subscription.AI points usage')}
|
||||
</Box>
|
||||
<Box
|
||||
fontSize={'14px'}
|
||||
fontWeight={'medium'}
|
||||
>{`${teamPlanStatus?.usedPoints || 0} / ${teamPlanStatus?.totalPoints ?? t('common:Unlimited')}`}</Box>
|
||||
</Flex>
|
||||
<Flex h={2} w={'full'} p={0.5} bg={'primary.50'} borderRadius={'md'}>
|
||||
<Box
|
||||
borderRadius={'sm'}
|
||||
transition="width 0.3s"
|
||||
w={`${teamPlanStatus?.totalPoints ? Math.max((teamPlanStatus.usedPoints / teamPlanStatus.totalPoints) * 100, 0) : 0}%`}
|
||||
bg={`${
|
||||
teamPlanStatus?.totalPoints
|
||||
? (teamPlanStatus.usedPoints / teamPlanStatus.totalPoints) * 100 < 50
|
||||
? 'primary'
|
||||
: (teamPlanStatus.usedPoints / teamPlanStatus.totalPoints) * 100 < 80
|
||||
? 'yellow'
|
||||
: 'red'
|
||||
: 'primary'
|
||||
}.500`}
|
||||
/>
|
||||
</Flex>
|
||||
</Box>
|
||||
<Box flex={1}>
|
||||
<Flex gap={4} alignItems={'center'} mb={2}>
|
||||
<Box fontSize={'16px'} fontWeight={'medium'} color={'myGray.900'}>
|
||||
{t('common:support.user.team.Dataset usage')}
|
||||
</Box>
|
||||
<Box
|
||||
fontSize={'14px'}
|
||||
fontWeight={'medium'}
|
||||
>{`${teamPlanStatus?.usedDatasetIndexSize || 0} / ${teamPlanStatus?.datasetMaxSize ?? t('common:Unlimited')}`}</Box>
|
||||
</Flex>
|
||||
<Flex h={2} w={'full'} p={0.5} bg={'primary.50'} borderRadius={'md'}>
|
||||
<Box
|
||||
borderRadius={'sm'}
|
||||
transition="width 0.3s"
|
||||
w={`${teamPlanStatus?.datasetMaxSize ? Math.max((teamPlanStatus.usedDatasetIndexSize / teamPlanStatus.datasetMaxSize) * 100, 0) : 0}%`}
|
||||
bg={`${
|
||||
teamPlanStatus?.datasetMaxSize
|
||||
? (teamPlanStatus.usedDatasetIndexSize / teamPlanStatus.datasetMaxSize) * 100 <
|
||||
50
|
||||
? 'primary'
|
||||
: (teamPlanStatus.usedDatasetIndexSize / teamPlanStatus.datasetMaxSize) *
|
||||
100 <
|
||||
80
|
||||
? 'yellow'
|
||||
: 'red'
|
||||
: 'primary'
|
||||
}.500`}
|
||||
/>
|
||||
</Flex>
|
||||
</Box>
|
||||
</Flex>
|
||||
|
||||
<FillRowTabs
|
||||
|
||||
@@ -15,10 +15,11 @@ import { useSystemStore } from '@/web/common/system/useSystemStore';
|
||||
import Markdown from '@/components/Markdown';
|
||||
import MyIcon from '@fastgpt/web/components/common/Icon';
|
||||
import { useToast } from '@fastgpt/web/hooks/useToast';
|
||||
import { type CreateBillResponse } from '@fastgpt/global/support/wallet/bill/api';
|
||||
import type { CreateBillResponseType } from '@fastgpt/global/openapi/support/wallet/bill/api';
|
||||
|
||||
export type QRPayProps = CreateBillResponse & {
|
||||
export type QRPayProps = CreateBillResponseType & {
|
||||
tip?: string;
|
||||
discountCouponName?: string;
|
||||
};
|
||||
|
||||
const QRCodePayModal = ({
|
||||
@@ -29,8 +30,14 @@ const QRCodePayModal = ({
|
||||
qrCode,
|
||||
iframeCode,
|
||||
markdown,
|
||||
onSuccess
|
||||
}: QRPayProps & { tip?: string; onSuccess?: () => any }) => {
|
||||
onSuccess,
|
||||
discountCouponName,
|
||||
onClose
|
||||
}: QRPayProps & {
|
||||
tip?: string;
|
||||
onSuccess?: () => any;
|
||||
onClose?: () => void;
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
const canvasRef = useRef<HTMLDivElement>(null);
|
||||
const toast = useToast();
|
||||
@@ -161,13 +168,25 @@ const QRCodePayModal = ({
|
||||
title={t('common:user.Pay')}
|
||||
iconSrc="/imgs/modal/wallet.svg"
|
||||
w={'600px'}
|
||||
onClose={onClose}
|
||||
>
|
||||
<ModalBody textAlign={'center'} padding={['16px 24px', '32px 52px']}>
|
||||
{tip && <LightTip text={tip} mb={6} textAlign={'left'} />}
|
||||
<Box>{t('common:pay_money')}</Box>
|
||||
<Box color="primary.600" fontSize="32px" fontWeight="600" lineHeight="40px" mb={6}>
|
||||
<Box
|
||||
color="primary.600"
|
||||
fontSize="32px"
|
||||
fontWeight="600"
|
||||
lineHeight="40px"
|
||||
mb={discountCouponName ? 1 : 6}
|
||||
>
|
||||
¥{readPrice.toFixed(2)}
|
||||
</Box>
|
||||
{discountCouponName && (
|
||||
<Box color={'myGray.900'} fontSize={'14px'} fontWeight={'500'} mb={6}>
|
||||
{t('common:discount_coupon_used') + t(discountCouponName)}
|
||||
</Box>
|
||||
)}
|
||||
|
||||
{renderPaymentContent()}
|
||||
|
||||
|
||||
@@ -34,29 +34,66 @@ const StandardPlanContentList = ({
|
||||
price: plan.price * (mode === SubModeEnum.month ? 1 : 10),
|
||||
level: level as `${StandardSubLevelEnum}`,
|
||||
...standardSubLevelMap[level as `${StandardSubLevelEnum}`],
|
||||
totalPoints:
|
||||
standplan?.totalPoints || plan.totalPoints * (mode === SubModeEnum.month ? 1 : 12),
|
||||
requestsPerMinute: standplan?.requestsPerMinute || plan.requestsPerMinute || 2000,
|
||||
maxTeamMember: standplan?.maxTeamMember || plan.maxTeamMember,
|
||||
maxAppAmount: standplan?.maxApp || plan.maxAppAmount,
|
||||
maxDatasetAmount: standplan?.maxDataset || plan.maxDatasetAmount,
|
||||
chatHistoryStoreDuration: plan.chatHistoryStoreDuration,
|
||||
maxDatasetSize: plan.maxDatasetSize,
|
||||
permissionCustomApiKey: plan.permissionCustomApiKey,
|
||||
permissionCustomCopyright: plan.permissionCustomCopyright,
|
||||
trainingWeight: plan.trainingWeight,
|
||||
totalPoints: plan.totalPoints * (mode === SubModeEnum.month ? 1 : 12),
|
||||
permissionWebsiteSync: plan.permissionWebsiteSync,
|
||||
permissionTeamOperationLog: plan.permissionTeamOperationLog
|
||||
maxDatasetSize: standplan?.maxDatasetSize || plan.maxDatasetSize,
|
||||
websiteSyncPerDataset: standplan?.websiteSyncPerDataset || plan.websiteSyncPerDataset,
|
||||
chatHistoryStoreDuration:
|
||||
standplan?.chatHistoryStoreDuration || plan.chatHistoryStoreDuration,
|
||||
auditLogStoreDuration: standplan?.auditLogStoreDuration || plan.auditLogStoreDuration,
|
||||
appRegistrationCount: standplan?.appRegistrationCount || plan.appRegistrationCount,
|
||||
ticketResponseTime: standplan?.ticketResponseTime || plan.ticketResponseTime
|
||||
};
|
||||
}, [
|
||||
subPlans?.standard,
|
||||
level,
|
||||
mode,
|
||||
standplan?.totalPoints,
|
||||
standplan?.requestsPerMinute,
|
||||
standplan?.maxTeamMember,
|
||||
standplan?.maxApp,
|
||||
standplan?.maxDataset
|
||||
standplan?.maxDataset,
|
||||
standplan?.maxDatasetSize,
|
||||
standplan?.websiteSyncPerDataset,
|
||||
standplan?.chatHistoryStoreDuration,
|
||||
standplan?.auditLogStoreDuration,
|
||||
standplan?.appRegistrationCount,
|
||||
standplan?.ticketResponseTime
|
||||
]);
|
||||
|
||||
return planContent ? (
|
||||
<Grid gap={4} fontSize={'sm'} fontWeight={500}>
|
||||
<Flex alignItems={'center'}>
|
||||
<MyIcon name={'price/right'} w={'16px'} mr={3} />
|
||||
<Flex alignItems={'center'}>
|
||||
<Box fontWeight={'bold'} color={'myGray.600'}>
|
||||
{t('common:support.wallet.subscription.function.Points', {
|
||||
amount: planContent.totalPoints
|
||||
})}
|
||||
</Box>
|
||||
<ModelPriceModal>
|
||||
{({ onOpen }) => (
|
||||
<QuestionTip
|
||||
ml={1}
|
||||
label={t('common:support.wallet.subscription.AI points click to read tip')}
|
||||
onClick={onOpen}
|
||||
/>
|
||||
)}
|
||||
</ModelPriceModal>
|
||||
</Flex>
|
||||
</Flex>
|
||||
<Flex alignItems={'center'}>
|
||||
<MyIcon name={'price/right'} w={'16px'} mr={3} />
|
||||
<Box fontWeight={'bold'} color={'myGray.600'}>
|
||||
{t('common:support.wallet.subscription.function.Max dataset size', {
|
||||
amount: planContent.maxDatasetSize
|
||||
})}
|
||||
</Box>
|
||||
</Flex>
|
||||
<Flex alignItems={'center'}>
|
||||
<MyIcon name={'price/right'} w={'16px'} mr={3} />
|
||||
<Box color={'myGray.600'}>
|
||||
@@ -89,52 +126,52 @@ const StandardPlanContentList = ({
|
||||
})}
|
||||
</Box>
|
||||
</Flex>
|
||||
<Flex alignItems={'center'}>
|
||||
<MyIcon name={'price/right'} w={'16px'} mr={3} />
|
||||
<Box fontWeight={'bold'} color={'myGray.600'}>
|
||||
{t('common:support.wallet.subscription.function.Max dataset size', {
|
||||
amount: planContent.maxDatasetSize
|
||||
})}
|
||||
</Box>
|
||||
</Flex>
|
||||
<Flex alignItems={'center'}>
|
||||
<MyIcon name={'price/right'} w={'16px'} mr={3} />
|
||||
<Flex alignItems={'center'}>
|
||||
<Box fontWeight={'bold'} color={'myGray.600'}>
|
||||
{t('common:support.wallet.subscription.function.Points', {
|
||||
amount: planContent.totalPoints
|
||||
})}
|
||||
</Box>
|
||||
<ModelPriceModal>
|
||||
{({ onOpen }) => (
|
||||
<QuestionTip
|
||||
ml={1}
|
||||
label={t('common:support.wallet.subscription.AI points click to read tip')}
|
||||
onClick={onOpen}
|
||||
/>
|
||||
)}
|
||||
</ModelPriceModal>
|
||||
</Flex>
|
||||
</Flex>
|
||||
<Flex alignItems={'center'}>
|
||||
<MyIcon name={'price/right'} w={'16px'} mr={3} />
|
||||
<Box color={'myGray.600'}>
|
||||
{t('common:support.wallet.subscription.Training weight', {
|
||||
weight: planContent.trainingWeight
|
||||
})}
|
||||
</Box>
|
||||
</Flex>
|
||||
{!!planContent.permissionWebsiteSync && (
|
||||
<Flex alignItems={'center'}>
|
||||
<MyIcon name={'price/right'} w={'16px'} mr={3} />
|
||||
<Box color={'myGray.600'}>{t('common:support.wallet.subscription.web_site_sync')}</Box>
|
||||
</Flex>
|
||||
)}
|
||||
{!!planContent.permissionTeamOperationLog && (
|
||||
{!!planContent.auditLogStoreDuration && (
|
||||
<Flex alignItems={'center'}>
|
||||
<MyIcon name={'price/right'} w={'16px'} mr={3} />
|
||||
<Box color={'myGray.600'}>
|
||||
{t('common:support.wallet.subscription.team_operation_log')}
|
||||
{t('common:support.wallet.subscription.function.Audit log store duration', {
|
||||
amount: planContent.auditLogStoreDuration
|
||||
})}
|
||||
</Box>
|
||||
</Flex>
|
||||
)}
|
||||
<Flex alignItems={'center'}>
|
||||
<MyIcon name={'price/right'} w={'16px'} mr={3} />
|
||||
<Box color={'myGray.600'}>
|
||||
{t('common:support.wallet.subscription.function.Requests per minute', {
|
||||
amount: planContent.requestsPerMinute
|
||||
})}
|
||||
</Box>
|
||||
<QuestionTip ml={1} label={t('common:support.wallet.subscription.function.qpm tip')} />
|
||||
</Flex>
|
||||
{!!planContent.websiteSyncPerDataset && (
|
||||
<Flex alignItems={'center'}>
|
||||
<MyIcon name={'price/right'} w={'16px'} mr={3} />
|
||||
<Box fontWeight={'bold'} color={'myGray.600'}>
|
||||
{t('common:support.wallet.subscription.function.Website sync per dataset', {
|
||||
amount: planContent.websiteSyncPerDataset
|
||||
})}
|
||||
</Box>
|
||||
</Flex>
|
||||
)}
|
||||
{!!planContent.ticketResponseTime && (
|
||||
<Flex alignItems={'center'}>
|
||||
<MyIcon name={'price/right'} w={'16px'} mr={3} />
|
||||
<Box color={'myGray.600'}>
|
||||
{t('common:support.wallet.subscription.function.Ticket response time', {
|
||||
amount: planContent.ticketResponseTime
|
||||
})}
|
||||
</Box>
|
||||
</Flex>
|
||||
)}
|
||||
{!!planContent.appRegistrationCount && (
|
||||
<Flex alignItems={'center'}>
|
||||
<MyIcon name={'price/right'} w={'16px'} mr={3} />
|
||||
<Box color={'myGray.600'}>
|
||||
{t('common:support.wallet.subscription.function.App registration count', {
|
||||
amount: planContent.appRegistrationCount
|
||||
})}
|
||||
</Box>
|
||||
</Flex>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user