From 587c9c932a8d940f05caa9d825e2695efdd13f74 Mon Sep 17 00:00:00 2001
From: heheer <1239331448@qq.com>
Date: Thu, 2 Jan 2025 17:28:41 +0800
Subject: [PATCH] optimize payment process
---
packages/global/common/error/code/team.ts | 1 +
.../service/support/permission/teamLimit.ts | 4 +-
.../web/components/common/Icon/constants.ts | 1 +
.../common/Icon/icons/common/wallet.svg | 4 +
packages/web/i18n/en/common.json | 4 +
packages/web/i18n/zh-CN/common.json | 4 +
packages/web/i18n/zh-Hant/common.json | 4 +
projects/app/src/components/Layout/index.tsx | 4 +-
.../wallet/NotSufficientModal/index.tsx | 159 +++++++++++++++---
projects/app/src/pages/account/team/index.tsx | 6 +-
.../dataset/component/ApiDatasetForm.tsx | 2 +-
.../src/pages/price/components/ExtraPlan.tsx | 23 +--
.../src/pages/price/components/Standard.tsx | 24 +--
projects/app/src/pages/price/index.tsx | 54 ++++--
projects/app/src/web/common/api/fetch.ts | 2 +-
projects/app/src/web/common/api/request.ts | 9 +-
.../src/web/common/system/useSystemStore.ts | 18 +-
17 files changed, 237 insertions(+), 86 deletions(-)
create mode 100644 packages/web/components/common/Icon/icons/common/wallet.svg
diff --git a/packages/global/common/error/code/team.ts b/packages/global/common/error/code/team.ts
index 8ad9abe021a2..80b3e658bb05 100644
--- a/packages/global/common/error/code/team.ts
+++ b/packages/global/common/error/code/team.ts
@@ -4,6 +4,7 @@ import { i18nT } from '../../../../web/i18n/utils';
export enum TeamErrEnum {
teamOverSize = 'teamOverSize',
unAuthTeam = 'unAuthTeam',
+ teamMemberOverSize = 'teamMemberOverSize',
aiPointsNotEnough = 'aiPointsNotEnough',
datasetSizeNotEnough = 'datasetSizeNotEnough',
datasetAmountNotEnough = 'datasetAmountNotEnough',
diff --git a/packages/service/support/permission/teamLimit.ts b/packages/service/support/permission/teamLimit.ts
index 814480ccf549..1a383f85b894 100644
--- a/packages/service/support/permission/teamLimit.ts
+++ b/packages/service/support/permission/teamLimit.ts
@@ -19,9 +19,7 @@ export const checkDatasetLimit = async ({
if (!standardConstants) return;
if (usedDatasetSize + insertLen >= datasetMaxSize) {
- return Promise.reject(
- `您的知识库容量为: ${datasetMaxSize}组,已使用: ${usedDatasetSize}组,导入当前文件需要: ${insertLen}组,请增加知识库容量后导入。`
- );
+ return Promise.reject(TeamErrEnum.datasetSizeNotEnough);
}
if (usedPoints >= totalPoints) {
diff --git a/packages/web/components/common/Icon/constants.ts b/packages/web/components/common/Icon/constants.ts
index 67b22d152a2c..850e0745b6b7 100644
--- a/packages/web/components/common/Icon/constants.ts
+++ b/packages/web/components/common/Icon/constants.ts
@@ -95,6 +95,7 @@ export const iconPaths = {
'common/variable': () => import('./icons/common/variable.svg'),
'common/viewLight': () => import('./icons/common/viewLight.svg'),
'common/voiceLight': () => import('./icons/common/voiceLight.svg'),
+ 'common/wallet': () => import('./icons/common/wallet.svg'),
'common/warn': () => import('./icons/common/warn.svg'),
'common/wechatFill': () => import('./icons/common/wechatFill.svg'),
configmap: () => import('./icons/configmap.svg'),
diff --git a/packages/web/components/common/Icon/icons/common/wallet.svg b/packages/web/components/common/Icon/icons/common/wallet.svg
new file mode 100644
index 000000000000..add3e92578c6
--- /dev/null
+++ b/packages/web/components/common/Icon/icons/common/wallet.svg
@@ -0,0 +1,4 @@
+
\ No newline at end of file
diff --git a/packages/web/i18n/en/common.json b/packages/web/i18n/en/common.json
index 21f3d856e01a..9722ecf668b3 100644
--- a/packages/web/i18n/en/common.json
+++ b/packages/web/i18n/en/common.json
@@ -1050,10 +1050,14 @@
"support.wallet.Ai point every thousand tokens_input": "Input:{{points}} points/1K tokens",
"support.wallet.Ai point every thousand tokens_output": "Output:{{points}} points/1K tokens",
"support.wallet.Amount": "Amount",
+ "support.wallet.App_amount_not_sufficient": "The number of your applications has reached the limit. Please upgrade your plan to continue using.",
"support.wallet.Buy": "Buy",
+ "support.wallet.Dataset_amount_not_sufficient": "The number of your datasets has reached the limit. Please upgrade your plan to continue using.",
+ "support.wallet.Dataset_not_sufficient": "Your dataset capacity is insufficient. Please upgrade your plan or purchase additional dataset capacity to continue using.",
"support.wallet.Not sufficient": "Insufficient AI Points, Please Upgrade Your Package or Purchase Additional AI Points to Continue Using.",
"support.wallet.Plan expired time": "Package Expiration Time",
"support.wallet.Standard Plan Detail": "Package Details",
+ "support.wallet.Team_member_over_size": "The number of your team members has reached the limit. Please upgrade your plan to continue using.",
"support.wallet.To read plan": "View Package",
"support.wallet.amount_0": "Purchase Quantity Cannot Be 0",
"support.wallet.apply_invoice": "Apply for Invoice",
diff --git a/packages/web/i18n/zh-CN/common.json b/packages/web/i18n/zh-CN/common.json
index e22b820b18d6..0d4e67b86574 100644
--- a/packages/web/i18n/zh-CN/common.json
+++ b/packages/web/i18n/zh-CN/common.json
@@ -1053,10 +1053,14 @@
"support.wallet.Ai point every thousand tokens_input": "输入:{{points}} 积分/1K tokens",
"support.wallet.Ai point every thousand tokens_output": "输出:{{points}} 积分/1K tokens",
"support.wallet.Amount": "金额",
+ "support.wallet.App_amount_not_sufficient": "您的应用数量已达上限,请升级套餐后继续使用。",
"support.wallet.Buy": "购买",
+ "support.wallet.Dataset_amount_not_sufficient": "您的知识库数量已达上限,请升级套餐后继续使用。",
+ "support.wallet.Dataset_not_sufficient": "您的知识库容量不足,请先升级套餐或购买额外知识库容量后继续使用。",
"support.wallet.Not sufficient": "您的 AI 积分不足,请先升级套餐或购买额外 AI 积分后继续使用。",
"support.wallet.Plan expired time": "套餐到期时间",
"support.wallet.Standard Plan Detail": "套餐详情",
+ "support.wallet.Team_member_over_size": "您的团队成员数量已达上限,请升级套餐后继续使用。",
"support.wallet.To read plan": "查看套餐",
"support.wallet.amount_0": "购买数量不能为0",
"support.wallet.apply_invoice": "申请开票",
diff --git a/packages/web/i18n/zh-Hant/common.json b/packages/web/i18n/zh-Hant/common.json
index 2b7804c8d4bc..3b7203078b56 100644
--- a/packages/web/i18n/zh-Hant/common.json
+++ b/packages/web/i18n/zh-Hant/common.json
@@ -1050,10 +1050,14 @@
"support.wallet.Ai point every thousand tokens_input": "輸入:{{points}} 积分/1K tokens",
"support.wallet.Ai point every thousand tokens_output": "輸出:{{points}} 积分/1K tokens",
"support.wallet.Amount": "金額",
+ "support.wallet.App_amount_not_sufficient": "您的應用數量已達上限,請升級套餐後繼續使用。",
"support.wallet.Buy": "購買",
+ "support.wallet.Dataset_amount_not_sufficient": "您的知識庫數量已達上限,請升級套餐後繼續使用。",
+ "support.wallet.Dataset_not_sufficient": "您的知識庫容量不足,請先升級套餐或購買額外知識庫容量後繼續使用。",
"support.wallet.Not sufficient": "您的 AI 點數不足,請先升級方案或購買額外 AI 點數後繼續使用。",
"support.wallet.Plan expired time": "方案到期時間",
"support.wallet.Standard Plan Detail": "方案詳細資訊",
+ "support.wallet.Team_member_over_size": "您的團隊成員數量已達上限,請升級套餐後繼續使用。",
"support.wallet.To read plan": "檢視方案",
"support.wallet.amount_0": "購買數量不能為 0",
"support.wallet.apply_invoice": "申請發票",
diff --git a/projects/app/src/components/Layout/index.tsx b/projects/app/src/components/Layout/index.tsx
index 2cebee18e501..a4f5ad80f071 100644
--- a/projects/app/src/components/Layout/index.tsx
+++ b/projects/app/src/components/Layout/index.tsx
@@ -48,7 +48,7 @@ export const navbarWidth = '64px';
const Layout = ({ children }: { children: JSX.Element }) => {
const router = useRouter();
const { Loading } = useLoading();
- const { loading, feConfigs, isNotSufficientModal } = useSystemStore();
+ const { loading, feConfigs, notSufficientModalType } = useSystemStore();
const { isPc } = useSystem();
const { userInfo } = useUserStore();
const { setUserDefaultLng } = useI18nLng();
@@ -113,7 +113,7 @@ const Layout = ({ children }: { children: JSX.Element }) => {
{feConfigs?.isPlus && (
<>
{!!userInfo && }
- {isNotSufficientModal && }
+ {notSufficientModalType && }
{!!userInfo && }
{!!userInfo && importantInforms.length > 0 && (
diff --git a/projects/app/src/components/support/wallet/NotSufficientModal/index.tsx b/projects/app/src/components/support/wallet/NotSufficientModal/index.tsx
index 94721c957757..3f413c4d3d4e 100644
--- a/projects/app/src/components/support/wallet/NotSufficientModal/index.tsx
+++ b/projects/app/src/components/support/wallet/NotSufficientModal/index.tsx
@@ -1,35 +1,148 @@
-import React from 'react';
+import React, { useMemo, useState } from 'react';
import MyModal from '@fastgpt/web/components/common/MyModal';
import { useTranslation } from 'next-i18next';
-import { Button, ModalBody, ModalFooter } from '@chakra-ui/react';
-import { useRouter } from 'next/router';
-import { useSystemStore } from '@/web/common/system/useSystemStore';
+import { Box, Button, Flex, ModalBody, ModalFooter, useDisclosure } from '@chakra-ui/react';
+import { NotSufficientModalType, useSystemStore } from '@/web/common/system/useSystemStore';
+import ExtraPlan from '@/pages/price/components/ExtraPlan';
+import StandardPlan from '@/pages/price/components/Standard';
+import FillRowTabs from '@fastgpt/web/components/common/Tabs/FillRowTabs';
+import FormLabel from '@fastgpt/web/components/common/MyBox/FormLabel';
+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';
-const NotSufficientModal = () => {
+const NotSufficientModal = ({ type }: { type: NotSufficientModalType }) => {
const { t } = useTranslation();
- const router = useRouter();
- const { setIsNotSufficientModal } = useSystemStore();
+ const { setNotSufficientModalType } = useSystemStore();
- const onClose = () => setIsNotSufficientModal(false);
+ const onClose = () => setNotSufficientModalType(undefined);
+
+ const {
+ isOpen: isRechargeModalOpen,
+ onOpen: onRechargeModalOpen,
+ onClose: onRechargeModalClose
+ } = useDisclosure();
+
+ const textMap = {
+ [TeamErrEnum.aiPointsNotEnough]: t('common:support.wallet.Not sufficient'),
+ [TeamErrEnum.datasetSizeNotEnough]: t('common:support.wallet.Dataset_not_sufficient'),
+ [TeamErrEnum.datasetAmountNotEnough]: t('common:support.wallet.Dataset_amount_not_sufficient'),
+ [TeamErrEnum.teamMemberOverSize]: t('common:support.wallet.Team_member_over_size'),
+ [TeamErrEnum.appAmountNotEnough]: t('common:support.wallet.App_amount_not_sufficient')
+ };
+
+ return (
+ <>
+
+ {textMap[type]}
+
+
+
+
+
+
+ {isRechargeModalOpen && (
+
+ )}
+ >
+ );
+};
+
+export default NotSufficientModal;
+
+const RechargeModal = ({
+ onClose,
+ onPaySuccess
+}: {
+ onClose: () => void;
+ onPaySuccess: () => void;
+}) => {
+ const { t } = useTranslation();
+ const { teamPlanStatus } = useUserStore();
+
+ const planName = useMemo(() => {
+ if (!teamPlanStatus?.standard?.currentSubLevel) return '';
+ return standardSubLevelMap[teamPlanStatus.standard.currentSubLevel].label;
+ }, [teamPlanStatus?.standard?.currentSubLevel]);
+
+ const [tab, setTab] = useState<'standard' | 'extra'>('standard');
return (
-
- {t('common:support.wallet.Not sufficient')}
-
-
-
-
+ {tab === 'standard' ? (
+
+ ) : (
+
+ )}
+
+
);
};
-
-export default NotSufficientModal;
diff --git a/projects/app/src/pages/account/team/index.tsx b/projects/app/src/pages/account/team/index.tsx
index 01f18c6512b8..e315ec584e3e 100644
--- a/projects/app/src/pages/account/team/index.tsx
+++ b/projects/app/src/pages/account/team/index.tsx
@@ -21,6 +21,7 @@ import { TeamContext, TeamModalContextProvider } from './components/context';
import dynamic from 'next/dynamic';
import TeamTagModal from '@/components/support/user/team/TeamTagModal';
import MemberTable from './components/MemberTable';
+import { TeamErrEnum } from '@fastgpt/global/common/error/code/team';
const InviteModal = dynamic(() => import('./components/InviteModal'));
const PermissionManage = dynamic(() => import('./components/PermissionManage/index'));
@@ -39,7 +40,7 @@ const Team = () => {
const { toast } = useToast();
const { t } = useTranslation();
const { userInfo, teamPlanStatus } = useUserStore();
- const { feConfigs } = useSystemStore();
+ const { feConfigs, setNotSufficientModalType } = useSystemStore();
const {
myTeams,
@@ -218,10 +219,11 @@ const Team = () => {
) {
toast({
status: 'warning',
- title: t('user.team.Over Max Member Tip', {
+ title: t('common:user.team.Over Max Member Tip', {
max: teamPlanStatus.standardConstants.maxTeamMember
})
});
+ setNotSufficientModalType(TeamErrEnum.teamMemberOverSize);
} else {
onOpenInvite();
}
diff --git a/projects/app/src/pages/dataset/component/ApiDatasetForm.tsx b/projects/app/src/pages/dataset/component/ApiDatasetForm.tsx
index 51c3f73be0b0..37a9f62b6ee3 100644
--- a/projects/app/src/pages/dataset/component/ApiDatasetForm.tsx
+++ b/projects/app/src/pages/dataset/component/ApiDatasetForm.tsx
@@ -135,7 +135,7 @@ const ApiDatasetForm = ({
diff --git a/projects/app/src/pages/price/components/ExtraPlan.tsx b/projects/app/src/pages/price/components/ExtraPlan.tsx
index a83d6a59bf00..84cd13b40998 100644
--- a/projects/app/src/pages/price/components/ExtraPlan.tsx
+++ b/projects/app/src/pages/price/components/ExtraPlan.tsx
@@ -1,4 +1,4 @@
-import { Box, Flex, Grid, Button } from '@chakra-ui/react';
+import { Box, Flex, Grid, Button, VStack } from '@chakra-ui/react';
import { useTranslation } from 'next-i18next';
import React, { useCallback, useState } from 'react';
import { useSystemStore } from '@/web/common/system/useSystemStore';
@@ -11,7 +11,7 @@ import { BillTypeEnum } from '@fastgpt/global/support/wallet/bill/constants';
import QRCodePayModal, { type QRPayProps } from '@/components/support/wallet/QRCodePayModal';
import MyNumberInput from '@fastgpt/web/components/common/Input/NumberInput';
-const ExtraPlan = () => {
+const ExtraPlan = ({ onPaySuccess }: { onPaySuccess?: () => void }) => {
const { t } = useTranslation();
const { toast } = useToast();
const { subPlans } = useSystemStore();
@@ -108,19 +108,8 @@ const ExtraPlan = () => {
);
return (
-
-
-
- {t('common:support.wallet.subscription.Extra plan tip')}
-
-
+
+
{
- {!!qrPayData && }
-
+ {!!qrPayData && }
+
);
};
diff --git a/projects/app/src/pages/price/components/Standard.tsx b/projects/app/src/pages/price/components/Standard.tsx
index 6180d9eb5109..ea3d0dc99b37 100644
--- a/projects/app/src/pages/price/components/Standard.tsx
+++ b/projects/app/src/pages/price/components/Standard.tsx
@@ -20,10 +20,10 @@ export enum PackageChangeStatusEnum {
const Standard = ({
standardPlan: myStandardPlan,
- refetchTeamSubPlan
+ onPaySuccess
}: {
standardPlan?: TeamSubSchema;
- refetchTeamSubPlan: () => void;
+ onPaySuccess?: () => void;
}) => {
const { t } = useTranslation();
@@ -78,14 +78,6 @@ const Standard = ({
return (
<>
-
- {t('common:support.wallet.subscription.Sub plan')}
-
-
- {t('common:support.wallet.subscription.Sub plan tip', {
- title: feConfigs?.systemTitle
- })}
-
{!!qrPayData && packageChange && (
-
+
)}
-
-
-
- {t('user:bill.standard_valid_tip')}
-
-
>
);
};
diff --git a/projects/app/src/pages/price/index.tsx b/projects/app/src/pages/price/index.tsx
index 581acfbb6f2a..c15bd4ea0b83 100644
--- a/projects/app/src/pages/price/index.tsx
+++ b/projects/app/src/pages/price/index.tsx
@@ -1,6 +1,6 @@
import React from 'react';
import { serviceSideProps } from '@fastgpt/web/common/system/nextjs';
-import { Box, Flex } from '@chakra-ui/react';
+import { Box, Flex, HStack, VStack } from '@chakra-ui/react';
import { useUserStore } from '@/web/support/user/useUserStore';
import { getTeamPlanStatus } from '@/web/support/user/team/api';
import { useQuery } from '@tanstack/react-query';
@@ -12,17 +12,18 @@ import FAQ from './components/FAQ';
import { getToken } from '@/web/support/user/auth';
import Script from 'next/script';
import { getWebReqUrl } from '@fastgpt/web/common/system/utils';
+import { useTranslation } from 'next-i18next';
+import MyIcon from '@fastgpt/web/components/common/Icon';
+import { useSystemStore } from '@/web/common/system/useSystemStore';
const PriceBox = () => {
const { userInfo } = useUserStore();
+ const { t } = useTranslation();
+ const { feConfigs } = useSystemStore();
- const { data: teamSubPlan, refetch: refetchTeamSubPlan } = useQuery(
- ['getTeamPlanStatus'],
- getTeamPlanStatus,
- {
- enabled: !!getToken() || !!userInfo
- }
- );
+ const { data: teamSubPlan } = useQuery(['getTeamPlanStatus'], getTeamPlanStatus, {
+ enabled: !!getToken() || !!userInfo
+ });
return (
<>
@@ -39,12 +40,39 @@ const PriceBox = () => {
backgroundRepeat={'no-repeat'}
>
{/* standard sub */}
-
+
+
+ {t('common:support.wallet.subscription.Sub plan')}
+
+
+ {t('common:support.wallet.subscription.Sub plan tip', {
+ title: feConfigs?.systemTitle
+ })}
+
+
+
+
+
+ {t('user:bill.standard_valid_tip')}
+
+
+
-
+ {/* extra plan */}
+
+
+
+ {t('common:support.wallet.subscription.Extra plan tip')}
+
+
+
{/* points */}
diff --git a/projects/app/src/web/common/api/fetch.ts b/projects/app/src/web/common/api/fetch.ts
index d3ed1b93b3f0..ba82ed797532 100644
--- a/projects/app/src/web/common/api/fetch.ts
+++ b/projects/app/src/web/common/api/fetch.ts
@@ -220,7 +220,7 @@ export const streamFetch = ({
});
} else if (event === SseResponseEventEnum.error) {
if (parseJson.statusText === TeamErrEnum.aiPointsNotEnough) {
- useSystemStore.getState().setIsNotSufficientModal(true);
+ useSystemStore.getState().setNotSufficientModalType(TeamErrEnum.aiPointsNotEnough);
}
errMsg = getErrText(parseJson, '流响应错误');
}
diff --git a/projects/app/src/web/common/api/request.ts b/projects/app/src/web/common/api/request.ts
index b5a7d61e5e93..9ab8aa4d4ec5 100644
--- a/projects/app/src/web/common/api/request.ts
+++ b/projects/app/src/web/common/api/request.ts
@@ -120,8 +120,13 @@ function responseError(err: any) {
return Promise.reject({ message: '无权操作' });
}
- if (err?.statusText === TeamErrEnum.aiPointsNotEnough) {
- useSystemStore.getState().setIsNotSufficientModal(true);
+ if (
+ err?.statusText === TeamErrEnum.aiPointsNotEnough ||
+ err?.statusText === TeamErrEnum.datasetSizeNotEnough ||
+ err?.statusText === TeamErrEnum.datasetAmountNotEnough ||
+ err?.statusText === TeamErrEnum.appAmountNotEnough
+ ) {
+ useSystemStore.getState().setNotSufficientModalType(err.statusText);
return Promise.reject(err);
}
if (err?.response?.data) {
diff --git a/projects/app/src/web/common/system/useSystemStore.ts b/projects/app/src/web/common/system/useSystemStore.ts
index a40122c90fdc..debbfc8ad762 100644
--- a/projects/app/src/web/common/system/useSystemStore.ts
+++ b/projects/app/src/web/common/system/useSystemStore.ts
@@ -14,9 +14,17 @@ import { InitDateResponse } from '@/global/common/api/systemRes';
import { FastGPTFeConfigsType } from '@fastgpt/global/common/system/types';
import { SubPlanType } from '@fastgpt/global/support/wallet/sub/type';
import { defaultWhisperModel } from '@fastgpt/global/core/ai/model';
+import { TeamErrEnum } from '@fastgpt/global/common/error/code/team';
type LoginStoreType = { provider: `${OAuthEnum}`; lastRoute: string; state: string };
+export type NotSufficientModalType =
+ | TeamErrEnum.datasetSizeNotEnough
+ | TeamErrEnum.aiPointsNotEnough
+ | TeamErrEnum.datasetAmountNotEnough
+ | TeamErrEnum.teamMemberOverSize
+ | TeamErrEnum.appAmountNotEnough;
+
type State = {
initd: boolean;
setInitd: () => void;
@@ -33,8 +41,8 @@ type State = {
gitStar: number;
loadGitStar: () => Promise;
- isNotSufficientModal: boolean;
- setIsNotSufficientModal: (val: boolean) => void;
+ notSufficientModalType: NotSufficientModalType | undefined;
+ setNotSufficientModalType: (val: NotSufficientModalType | undefined) => void;
initDataBufferId?: string;
feConfigs: FastGPTFeConfigsType;
@@ -105,10 +113,10 @@ export const useSystemStore = create()(
} catch (error) {}
},
- isNotSufficientModal: false,
- setIsNotSufficientModal(val: boolean) {
+ notSufficientModalType: undefined,
+ setNotSufficientModalType(type: NotSufficientModalType | undefined) {
set((state) => {
- state.isNotSufficientModal = val;
+ state.notSufficientModalType = type;
});
},