From c1d08c0ccc5e4fc3f68e0c311b0e3c164acfe39a Mon Sep 17 00:00:00 2001 From: Archer <545436317@qq.com> Date: Mon, 26 Aug 2024 09:52:09 +0800 Subject: [PATCH] New pay (#2484) (#2510) * New pay (#2484) * remove sub status * feat: new pay mode * fix: ts * limit --- packages/global/support/wallet/bill/api.d.ts | 29 ++- packages/global/support/wallet/bill/type.d.ts | 1 - .../global/support/wallet/sub/constants.ts | 40 ++- packages/global/support/wallet/sub/type.d.ts | 9 +- packages/service/support/wallet/sub/schema.ts | 31 +-- packages/service/support/wallet/sub/utils.ts | 70 ++++-- packages/web/i18n/en/common.json | 3 +- packages/web/i18n/en/user.json | 4 +- packages/web/i18n/zh/common.json | 5 +- packages/web/i18n/zh/user.json | 4 +- .../support/wallet/QRCodePayModal.tsx | 13 +- .../src/pages/account/components/PayModal.tsx | 116 --------- .../user/team/plan/getTeamPlanStatus.ts | 33 +-- .../Flow/NodeTemplatesModal.tsx | 1 + .../src/pages/price/components/Standard.tsx | 229 ++++-------------- projects/app/src/pages/price/index.tsx | 6 +- .../app/src/web/support/wallet/sub/api.ts | 16 -- 17 files changed, 170 insertions(+), 440 deletions(-) delete mode 100644 projects/app/src/pages/account/components/PayModal.tsx delete mode 100644 projects/app/src/web/support/wallet/sub/api.ts diff --git a/packages/global/support/wallet/bill/api.d.ts b/packages/global/support/wallet/bill/api.d.ts index e53e75ac3..1e9bca452 100644 --- a/packages/global/support/wallet/bill/api.d.ts +++ b/packages/global/support/wallet/bill/api.d.ts @@ -1,16 +1,25 @@ +import { StandardSubLevelEnum, SubModeEnum } from '../sub/constants'; import { BillTypeEnum } from './constants'; -export type CreateBillProps = { - type: BillTypeEnum; - - // balance - balance?: number; // read - - month?: number; - // extra dataset size - extraDatasetSize?: number; // 1k - extraPoints?: number; // 100w +export type CreateStandPlanBill = { + type: BillTypeEnum.standSubPlan; + level: `${StandardSubLevelEnum}`; + subMode: `${SubModeEnum}`; }; +type CreateExtractPointsBill = { + type: BillTypeEnum.extraPoints; + extraPoints: number; +}; +type CreateExtractDatasetBill = { + type: BillTypeEnum.extraDatasetSub; + extraDatasetSize: number; + month: number; +}; +export type CreateBillProps = + | CreateStandPlanBill + | CreateExtractPointsBill + | CreateExtractDatasetBill; + export type CreateBillResponse = { billId: string; codeUrl: string; diff --git a/packages/global/support/wallet/bill/type.d.ts b/packages/global/support/wallet/bill/type.d.ts index 2820bc37c..51b52f1be 100644 --- a/packages/global/support/wallet/bill/type.d.ts +++ b/packages/global/support/wallet/bill/type.d.ts @@ -19,7 +19,6 @@ export type BillSchemaType = { month?: number; datasetSize?: number; extraPoints?: number; - invoice: boolean; }; }; diff --git a/packages/global/support/wallet/sub/constants.ts b/packages/global/support/wallet/sub/constants.ts index 4516e0151..997a43df0 100644 --- a/packages/global/support/wallet/sub/constants.ts +++ b/packages/global/support/wallet/sub/constants.ts @@ -1,3 +1,5 @@ +import { i18nT } from '../../../../web/i18n/utils'; + export enum SubTypeEnum { standard = 'standard', extraDatasetSize = 'extraDatasetSize', @@ -19,19 +21,6 @@ export const subTypeMap = { } }; -export enum SubStatusEnum { - active = 'active', - expired = 'expired' -} -export const subStatusMap = { - [SubStatusEnum.active]: { - label: 'support.wallet.subscription.status.active' - }, - [SubStatusEnum.expired]: { - label: 'support.wallet.subscription.status.canceled' - } -}; - export enum SubModeEnum { month = 'month', year = 'year' @@ -56,23 +45,28 @@ export enum StandardSubLevelEnum { } export const standardSubLevelMap = { [StandardSubLevelEnum.free]: { - label: 'support.wallet.subscription.standardSubLevel.free', - desc: 'support.wallet.subscription.standardSubLevel.free desc' + label: i18nT('common:support.wallet.subscription.standardSubLevel.free'), + desc: i18nT('common:support.wallet.subscription.standardSubLevel.free desc'), + weight: 1 }, [StandardSubLevelEnum.experience]: { - label: 'support.wallet.subscription.standardSubLevel.experience', - desc: '' + label: i18nT('common:support.wallet.subscription.standardSubLevel.experience'), + desc: '', + weight: 2 }, [StandardSubLevelEnum.team]: { - label: 'support.wallet.subscription.standardSubLevel.team', - desc: '' + label: i18nT('common:support.wallet.subscription.standardSubLevel.team'), + desc: '', + weight: 3 }, [StandardSubLevelEnum.enterprise]: { - label: 'support.wallet.subscription.standardSubLevel.enterprise', - desc: '' + label: i18nT('common:support.wallet.subscription.standardSubLevel.enterprise'), + desc: '', + weight: 4 }, [StandardSubLevelEnum.custom]: { - label: 'support.wallet.subscription.standardSubLevel.custom', - desc: '' + label: i18nT('common:support.wallet.subscription.standardSubLevel.custom'), + desc: '', + weight: 5 } }; diff --git a/packages/global/support/wallet/sub/type.d.ts b/packages/global/support/wallet/sub/type.d.ts index ab7355f7e..2a2af2ed8 100644 --- a/packages/global/support/wallet/sub/type.d.ts +++ b/packages/global/support/wallet/sub/type.d.ts @@ -1,4 +1,4 @@ -import { StandardSubLevelEnum, SubModeEnum, SubStatusEnum, SubTypeEnum } from './constants'; +import { StandardSubLevelEnum, SubModeEnum, SubTypeEnum } from './constants'; // Content of plan export type TeamStandardSubPlanItemType = { @@ -36,17 +36,14 @@ export type TeamSubSchema = { _id: string; teamId: string; type: `${SubTypeEnum}`; - status: `${SubStatusEnum}`; startTime: Date; expiredTime: Date; - price: number; currentMode: `${SubModeEnum}`; nextMode: `${SubModeEnum}`; - currentSubLevel: `${StandardSubLevelEnum}`; - nextSubLevel: `${StandardSubLevelEnum}`; + currentSubLevel: StandardSubLevelEnum; + nextSubLevel: StandardSubLevelEnum; - pointPrice: number; totalPoints: number; surplusPoints: number; diff --git a/packages/service/support/wallet/sub/schema.ts b/packages/service/support/wallet/sub/schema.ts index c13086d94..aa838e25b 100644 --- a/packages/service/support/wallet/sub/schema.ts +++ b/packages/service/support/wallet/sub/schema.ts @@ -7,10 +7,9 @@ import { connectionMongo, getMongoModel } from '../../../common/mongo'; const { Schema } = connectionMongo; import { TeamCollectionName } from '@fastgpt/global/support/user/team/constant'; import { - standardSubLevelMap, - subModeMap, - subStatusMap, - subTypeMap + StandardSubLevelEnum, + SubModeEnum, + SubTypeEnum } from '@fastgpt/global/support/wallet/sub/constants'; import type { TeamSubSchema } from '@fastgpt/global/support/wallet/sub/type'; @@ -24,12 +23,7 @@ const SubSchema = new Schema({ }, type: { type: String, - enum: Object.keys(subTypeMap), - required: true - }, - status: { - type: String, - enum: Object.keys(subStatusMap), + enum: Object.values(SubTypeEnum), required: true }, startTime: { @@ -40,38 +34,29 @@ const SubSchema = new Schema({ type: Date, required: true }, - price: { - // last sub pay price(total price) - type: Number, - required: true - }, // standard sub currentMode: { type: String, - enum: Object.keys(subModeMap) + enum: Object.values(SubModeEnum) }, nextMode: { type: String, - enum: Object.keys(subModeMap) + enum: Object.values(SubModeEnum) }, currentSubLevel: { type: String, - enum: Object.keys(standardSubLevelMap) + enum: Object.values(StandardSubLevelEnum) }, nextSubLevel: { type: String, - enum: Object.keys(standardSubLevelMap) + enum: Object.values(StandardSubLevelEnum) }, // stand sub and extra points sub. Plan total points totalPoints: { type: Number }, - pointPrice: { - // stand level point total price - type: Number - }, surplusPoints: { // plan surplus points type: Number diff --git a/packages/service/support/wallet/sub/utils.ts b/packages/service/support/wallet/sub/utils.ts index 75fc803a8..1ada11ad3 100644 --- a/packages/service/support/wallet/sub/utils.ts +++ b/packages/service/support/wallet/sub/utils.ts @@ -1,26 +1,45 @@ import { StandardSubLevelEnum, SubModeEnum, - SubStatusEnum, - SubTypeEnum + SubTypeEnum, + standardSubLevelMap } from '@fastgpt/global/support/wallet/sub/constants'; import { MongoTeamSub } from './schema'; -import { FeTeamPlanStatusType } from '@fastgpt/global/support/wallet/sub/type.d'; +import { FeTeamPlanStatusType, TeamSubSchema } from '@fastgpt/global/support/wallet/sub/type.d'; import { getVectorCountByTeamId } from '../../../common/vectorStore/controller'; import dayjs from 'dayjs'; import { ClientSession } from '../../../common/mongo'; import { addMonths } from 'date-fns'; +import { readFromSecondary } from '../../../common/mongo/utils'; -export const getStandardPlans = () => { +export const getStandardPlansConfig = () => { return global?.subPlans?.standard; }; -export const getStandardPlan = (level: `${StandardSubLevelEnum}`) => { +export const getStandardPlanConfig = (level: `${StandardSubLevelEnum}`) => { return global.subPlans?.standard?.[level]; }; +export const sortStandPlans = (plans: TeamSubSchema[]) => { + return plans.sort( + (a, b) => + standardSubLevelMap[b.currentSubLevel].weight - standardSubLevelMap[a.currentSubLevel].weight + ); +}; export const getTeamStandPlan = async ({ teamId }: { teamId: string }) => { + const plans = await MongoTeamSub.find( + { + teamId, + type: SubTypeEnum.standard + }, + undefined, + { + ...readFromSecondary + } + ); + sortStandPlans(plans); + const standardPlans = global.subPlans?.standard; - const standard = await MongoTeamSub.findOne({ teamId, type: SubTypeEnum.standard }).lean(); + const standard = plans[0]; return { [SubTypeEnum.standard]: standard, @@ -38,12 +57,11 @@ export const initTeamStandardPlan2Free = async ({ teamId: string; session?: ClientSession; }) => { - const freePoints = global?.subPlans?.standard?.free?.totalPoints || 100; + const freePoints = global?.subPlans?.standard?.[StandardSubLevelEnum.free]?.totalPoints || 100; const teamStandardSub = await MongoTeamSub.findOne({ teamId, type: SubTypeEnum.standard }); if (teamStandardSub) { - teamStandardSub.status = SubStatusEnum.active; teamStandardSub.currentMode = SubModeEnum.month; teamStandardSub.nextMode = SubModeEnum.month; teamStandardSub.startTime = new Date(); @@ -52,9 +70,6 @@ export const initTeamStandardPlan2Free = async ({ teamStandardSub.currentSubLevel = StandardSubLevelEnum.free; teamStandardSub.nextSubLevel = StandardSubLevelEnum.free; - teamStandardSub.price = 0; - teamStandardSub.pointPrice = 0; - teamStandardSub.totalPoints = freePoints; teamStandardSub.surplusPoints = teamStandardSub.surplusPoints && teamStandardSub.surplusPoints < 0 @@ -68,13 +83,10 @@ export const initTeamStandardPlan2Free = async ({ { teamId, type: SubTypeEnum.standard, - status: SubStatusEnum.active, currentMode: SubModeEnum.month, nextMode: SubModeEnum.month, startTime: new Date(), expiredTime: addMonths(new Date(), 1), - price: 0, - pointPrice: 0, currentSubLevel: StandardSubLevelEnum.free, nextSubLevel: StandardSubLevelEnum.free, @@ -94,21 +106,27 @@ export const getTeamPlanStatus = async ({ }): Promise => { const standardPlans = global.subPlans?.standard; + /* Get all plans and datasetSize */ const [plans, usedDatasetSize] = await Promise.all([ MongoTeamSub.find({ teamId }).lean(), getVectorCountByTeamId(teamId) ]); - const standard = plans.find((plan) => plan.type === SubTypeEnum.standard); + /* Get all standardPlans and active standardPlan */ + const teamStandardPlans = sortStandPlans( + plans.filter((plan) => plan.type === SubTypeEnum.standard) + ); + const standardPlan = teamStandardPlans[0]; + const extraDatasetSize = plans.filter((plan) => plan.type === SubTypeEnum.extraDatasetSize); const extraPoints = plans.filter((plan) => plan.type === SubTypeEnum.extraPoints); // Free user, first login after expiration. The free subscription plan will be reset if ( - standard && - standard.expiredTime && - standard.currentSubLevel === StandardSubLevelEnum.free && - dayjs(standard.expiredTime).isBefore(new Date()) + standardPlan && + standardPlan.expiredTime && + standardPlan.currentSubLevel === StandardSubLevelEnum.free && + dayjs(standardPlan.expiredTime).isBefore(new Date()) ) { console.log('Init free stand plan', { teamId }); await initTeamStandardPlan2Free({ teamId }); @@ -116,26 +134,26 @@ export const getTeamPlanStatus = async ({ } const totalPoints = standardPlans - ? (standard?.totalPoints || 0) + + ? (standardPlan?.totalPoints || 0) + extraPoints.reduce((acc, cur) => acc + (cur.totalPoints || 0), 0) : Infinity; const surplusPoints = - (standard?.surplusPoints || 0) + + (standardPlan?.surplusPoints || 0) + extraPoints.reduce((acc, cur) => acc + (cur.surplusPoints || 0), 0); const standardMaxDatasetSize = - standard?.currentSubLevel && standardPlans - ? standardPlans[standard.currentSubLevel]?.maxDatasetSize || Infinity + standardPlan?.currentSubLevel && standardPlans + ? standardPlans[standardPlan.currentSubLevel]?.maxDatasetSize || Infinity : Infinity; const totalDatasetSize = standardMaxDatasetSize + extraDatasetSize.reduce((acc, cur) => acc + (cur.currentExtraDatasetSize || 0), 0); return { - [SubTypeEnum.standard]: standard, + [SubTypeEnum.standard]: standardPlan, standardConstants: - standard?.currentSubLevel && standardPlans - ? standardPlans[standard.currentSubLevel] + standardPlan?.currentSubLevel && standardPlans + ? standardPlans[standardPlan.currentSubLevel] : undefined, totalPoints, diff --git a/packages/web/i18n/en/common.json b/packages/web/i18n/en/common.json index e9620b478..029e3db04 100644 --- a/packages/web/i18n/en/common.json +++ b/packages/web/i18n/en/common.json @@ -1331,7 +1331,7 @@ "FAQ": "Frequently asked questions", "Month amount": "Months", "Next plan": "Future plan", - "Nonsupport": "Unable to switch", + "Nonsupport": "No purchase required", "Stand plan level": "Subscription plan", "Standard update fail": "Failed to modify subscription plan", "Standard update success": "Subscription plan change successful!", @@ -1360,6 +1360,7 @@ "point": "integral", "rerank": "Rerank", "standardSubLevel": { + "custom": "Customized version", "enterprise": "Enterprise edition", "experience": "Experience edition", "free": "Free edition", diff --git a/packages/web/i18n/en/user.json b/packages/web/i18n/en/user.json index 5f798cdf0..f3847cb74 100644 --- a/packages/web/i18n/en/user.json +++ b/packages/web/i18n/en/user.json @@ -1,6 +1,8 @@ { "bill": { - "not_need_invoice": "Balance payment, unable to issue invoice" + "buy_standard_plan_success": "Package purchased successfully", + "not_need_invoice": "Balance payment, unable to issue invoice", + "renew_plan": "Renewal package" }, "bind_inform_account_error": "Abnormal binding notification account", "bind_inform_account_success": "Binding notification account successful", diff --git a/packages/web/i18n/zh/common.json b/packages/web/i18n/zh/common.json index d1030b400..65028ed89 100644 --- a/packages/web/i18n/zh/common.json +++ b/packages/web/i18n/zh/common.json @@ -1116,7 +1116,7 @@ "old_package_price": "旧套餐余额", "other": "其他金额,请取整数", "to_recharge": "余额不足,去充值", - "wechat": "请微信扫码支付: {{price}}元,请勿关闭页面", + "wechat": "请微信扫码支付: {{price}}元\n请勿关闭页面", "yuan": "{{amount}}元" }, "permission": { @@ -1331,7 +1331,7 @@ "FAQ": "常见问题", "Month amount": "月数", "Next plan": "未来套餐", - "Nonsupport": "无法切换", + "Nonsupport": "无需购买", "Stand plan level": "订阅套餐", "Standard update fail": "修改订阅套餐异常", "Standard update success": "变更订阅套餐成功!", @@ -1360,6 +1360,7 @@ "point": "积分", "rerank": "检索结果重排", "standardSubLevel": { + "custom": "自定义版", "enterprise": "企业版", "experience": "体验版", "free": "免费版", diff --git a/packages/web/i18n/zh/user.json b/packages/web/i18n/zh/user.json index 7ff0d9c3d..3c600c4a9 100644 --- a/packages/web/i18n/zh/user.json +++ b/packages/web/i18n/zh/user.json @@ -11,7 +11,9 @@ "use_balance_hint": "由于系统升级,原“自动续费从余额扣款”模式取消,余额充值入口关闭。您的余额可用于购买积分", "contact_customer_service": "联系客服", "convert_success": "兑换成功", - "convert_error": "兑换失败" + "convert_error": "兑换失败", + "buy_standard_plan_success": "购买套餐成功", + "renew_plan": "续费套餐" }, "bind_inform_account_error": "绑定通知账号异常", "bind_inform_account_success": "绑定通知账号成功", diff --git a/projects/app/src/components/support/wallet/QRCodePayModal.tsx b/projects/app/src/components/support/wallet/QRCodePayModal.tsx index 60a86917f..ba49eeb9e 100644 --- a/projects/app/src/components/support/wallet/QRCodePayModal.tsx +++ b/projects/app/src/components/support/wallet/QRCodePayModal.tsx @@ -1,7 +1,7 @@ import MyModal from '@fastgpt/web/components/common/MyModal'; import React, { useEffect } from 'react'; import { useTranslation } from 'next-i18next'; -import { Box, ModalBody, ModalFooter } from '@chakra-ui/react'; +import { Box, ModalBody } from '@chakra-ui/react'; import { useQuery } from '@tanstack/react-query'; import { checkBalancePayResult } from '@/web/support/wallet/bill/api'; import { useToast } from '@fastgpt/web/hooks/useToast'; @@ -15,11 +15,12 @@ export type QRPayProps = { }; const QRCodePayModal = ({ + tip, readPrice, codeUrl, billId, onSuccess -}: QRPayProps & { onSuccess?: () => any }) => { +}: QRPayProps & { tip?: string; onSuccess?: () => any }) => { const router = useRouter(); const { t } = useTranslation(); const { toast } = useToast(); @@ -72,11 +73,13 @@ const QRCodePayModal = ({ return ( - - {t('common:pay.wechat', { price: readPrice })} + + {tip && {tip}} + + {t('common:pay.wechat', { price: readPrice })} + - ); }; diff --git a/projects/app/src/pages/account/components/PayModal.tsx b/projects/app/src/pages/account/components/PayModal.tsx deleted file mode 100644 index dfb3a9699..000000000 --- a/projects/app/src/pages/account/components/PayModal.tsx +++ /dev/null @@ -1,116 +0,0 @@ -import React, { useState, useCallback, useMemo } from 'react'; -import { ModalFooter, ModalBody, Button, Input, Box, Grid, Link } from '@chakra-ui/react'; -import { getWxPayQRCode } from '@/web/support/wallet/bill/api'; -import { useToast } from '@fastgpt/web/hooks/useToast'; -import { useRouter } from 'next/router'; -import { getErrText } from '@fastgpt/global/common/error/utils'; -import { useTranslation } from 'next-i18next'; -import MyModal from '@fastgpt/web/components/common/MyModal'; -import { BillTypeEnum } from '@fastgpt/global/support/wallet/bill/constants'; -import QRCodePayModal, { type QRPayProps } from '@/components/support/wallet/QRCodePayModal'; -import { useSystemStore } from '@/web/common/system/useSystemStore'; -import { EXTRA_PLAN_CARD_ROUTE } from '@/web/support/wallet/sub/constants'; - -const PayModal = ({ - onClose, - defaultValue, - onSuccess -}: { - defaultValue?: number; - onClose: () => void; - onSuccess?: () => any; -}) => { - const { t } = useTranslation(); - const { toast } = useToast(); - const { subPlans } = useSystemStore(); - const [inputVal, setInputVal] = useState(defaultValue); - const [loading, setLoading] = useState(false); - const [qrPayData, setQRPayData] = useState(); - const handleClickPay = useCallback(async () => { - if (!inputVal || inputVal <= 0 || isNaN(+inputVal)) return; - setLoading(true); - try { - // 获取支付二维码 - const res = await getWxPayQRCode({ - type: BillTypeEnum.balance, - balance: inputVal - }); - setQRPayData({ - readPrice: res.readPrice, - codeUrl: res.codeUrl, - billId: res.billId - }); - } catch (err) { - toast({ - title: getErrText(err), - status: 'error' - }); - } - setLoading(false); - }, [inputVal, toast]); - - const payList = useMemo(() => { - const list = Object.values(subPlans?.standard || {}); - const priceList = list.map((item) => item.price); - return priceList.concat(priceList.map((item) => item * 10)).filter(Boolean); - }, [subPlans?.standard]); - - return ( - - - - 该余额仅用于自动续费标准套餐。如需购买额外套餐,可 - - 直接下单 - - ,无需充值余额。 - - - {payList.map((item) => ( - - ))} - - - { - setInputVal(Math.floor(+e.target.value)); - }} - > - - - - - - - - - {!!qrPayData && } - - ); -}; - -export default PayModal; diff --git a/projects/app/src/pages/api/support/user/team/plan/getTeamPlanStatus.ts b/projects/app/src/pages/api/support/user/team/plan/getTeamPlanStatus.ts index f138d9990..0d0dd7e10 100644 --- a/projects/app/src/pages/api/support/user/team/plan/getTeamPlanStatus.ts +++ b/projects/app/src/pages/api/support/user/team/plan/getTeamPlanStatus.ts @@ -1,28 +1,17 @@ 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 { FeTeamPlanStatusType } from '@fastgpt/global/support/wallet/sub/type'; import { getTeamPlanStatus } from '@fastgpt/service/support/wallet/sub/utils'; +import { NextAPI } from '@/service/middleware/entry'; -export default async function handler(req: NextApiRequest, res: NextApiResponse) { - try { - await connectToDatabase(); +async function handler(req: NextApiRequest, res: NextApiResponse) { + const { teamId } = await authCert({ + req, + authToken: true + }); - const { teamId } = await authCert({ - req, - authToken: true - }); - - jsonRes(res, { - data: await getTeamPlanStatus({ - teamId - }) - }); - } catch (err) { - jsonRes(res, { - code: 500, - error: err - }); - } + return getTeamPlanStatus({ + teamId + }); } + +export default NextAPI(handler); diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/NodeTemplatesModal.tsx b/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/NodeTemplatesModal.tsx index 84076bfb5..7ed10f6a0 100644 --- a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/NodeTemplatesModal.tsx +++ b/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/NodeTemplatesModal.tsx @@ -123,6 +123,7 @@ const NodeTemplatesModal = ({ isOpen, onClose }: ModuleTemplateListProps) => { }, { manual: false, + throttleWait: 100, refreshDeps: [basicNodeTemplates, nodeList, hasToolNode, templateType] } ); diff --git a/projects/app/src/pages/price/components/Standard.tsx b/projects/app/src/pages/price/components/Standard.tsx index 6ca39f08f..6ac481bda 100644 --- a/projects/app/src/pages/price/components/Standard.tsx +++ b/projects/app/src/pages/price/components/Standard.tsx @@ -1,33 +1,21 @@ import React, { useMemo, useState } from 'react'; import MyIcon from '@fastgpt/web/components/common/Icon'; -import { Box, Button, Flex, Grid, ModalBody, ModalFooter } from '@chakra-ui/react'; +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 { 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, useRequest2 } from '@fastgpt/web/hooks/useRequest'; -import { StandardSubPlanUpdateResponse } from '@fastgpt/global/support/wallet/sub/api.d'; -import { formatStorePrice2Read } from '@fastgpt/global/support/wallet/usage/tools'; +import { useRequest2 } from '@fastgpt/web/hooks/useRequest'; import { TeamSubSchema } from '@fastgpt/global/support/wallet/sub/type'; -import MyModal from '@fastgpt/web/components/common/MyModal'; import QRCodePayModal, { type QRPayProps } from '@/components/support/wallet/QRCodePayModal'; import { getWxPayQRCode } from '@/web/support/wallet/bill/api'; import { BillTypeEnum } from '@fastgpt/global/support/wallet/bill/constants'; import StandardPlanContentList from '@/components/support/wallet/StandardPlanContentList'; import { useRouter } from 'next/router'; - -type ConfirmPayModalProps = { - teamBalance: number; - totalPrice: number; - payPrice: number; - - planProps: StandardSubPlanParams; -}; +import { useToast } from '@fastgpt/web/hooks/useToast'; const Standard = ({ - standardPlan, + standardPlan: myStandardPlan, refetchTeamSubPlan }: { standardPlan?: TeamSubSchema; @@ -35,8 +23,9 @@ const Standard = ({ }) => { const { t } = useTranslation(); const router = useRouter(); + const { toast } = useToast(); + const { subPlans, feConfigs } = useSystemStore(); - const [confirmPayData, setConfirmPayData] = useState(); const [selectSubMode, setSelectSubMode] = useState<`${SubModeEnum}`>(SubModeEnum.month); const standardSubList = useMemo(() => { @@ -62,37 +51,17 @@ const Standard = ({ : []; }, [subPlans?.standard, selectSubMode]); - const { runAsync: onclickUpdateStandardPlan, loading: isUpdatingStandardPlan } = useRequest2( - postUpdateStandardSub, - { - onSuccess() { - refetchTeamSubPlan(); - router.reload(); - }, - successToast: t('common:support.wallet.subscription.Standard update success'), - errorToast: t('common:support.wallet.subscription.Standard update fail') - } - ); + // Pay code + const [qrPayData, setQRPayData] = useState(); - const { mutate: onclickPreCheckStandPlan, isLoading: isCheckingStandardPlan } = useRequest({ - mutationFn: (data: StandardSubPlanParams) => postCheckStandardSub(data), - onSuccess(res: StandardSubPlanUpdateResponse) { - if (res.payPrice === undefined) { - onclickUpdateStandardPlan({ - level: res.nextSubLevel, - mode: res.nextMode - }); - } else { - setConfirmPayData({ - teamBalance: res.teamBalance, - totalPrice: res.planPrice, - payPrice: res.payPrice, - planProps: { - level: res.nextSubLevel, - mode: res.nextMode - } - }); - } + /* Get pay code */ + const { runAsync: onPay, loading: isLoading } = useRequest2(getWxPayQRCode, { + onSuccess(res) { + setQRPayData({ + readPrice: res.readPrice, + codeUrl: res.codeUrl, + billId: res.billId + }); } }); @@ -136,9 +105,7 @@ const Standard = ({ minH={'550px'} > {standardSubList.map((item) => { - const isCurrentPlan = - item.level === standardPlan?.currentSubLevel && - selectSubMode === standardPlan?.currentMode; + const isCurrentPlan = item.level === myStandardPlan?.currentSubLevel; return ( - {t(item.label as any)} + {t(item.label)} ¥{item.price} @@ -166,46 +133,44 @@ const Standard = ({ {t(item.desc as any, { title: feConfigs?.systemTitle })} + + {/* Button */} {(() => { - if ( - item.level === StandardSubLevelEnum.free && - selectSubMode === SubModeEnum.year - ) { + if (item.level === StandardSubLevelEnum.free) { return ( ); } - if ( - item.level === standardPlan?.nextSubLevel && - selectSubMode === standardPlan?.nextMode - ) { - return ( - - ); - } + // feature: + // if ( + // item.level === myStandardPlan?.nextSubLevel && + // selectSubMode === myStandardPlan?.nextMode + // ) { + // return ( + // + // ); + // } if (isCurrentPlan) { return ( ); } @@ -216,11 +181,12 @@ const Standard = ({ mb={6} w={'100%'} variant={'primaryGhost'} - isLoading={isUpdatingStandardPlan || isCheckingStandardPlan} + isLoading={isLoading} onClick={() => - onclickPreCheckStandPlan({ + onPay({ + type: BillTypeEnum.standSubPlan, level: item.level, - mode: selectSubMode + subMode: selectSubMode }) } > @@ -236,13 +202,7 @@ const Standard = ({ })} - {!!confirmPayData && ( - setConfirmPayData(undefined)} - onConfirmPay={() => onclickUpdateStandardPlan(confirmPayData.planProps)} - /> - )} + {!!qrPayData && } ); }; @@ -301,100 +261,3 @@ const RowTabs = ({ ); }; - -const ConfirmPayModal = ({ - teamBalance, - totalPrice, - payPrice, - onClose, - onConfirmPay -}: ConfirmPayModalProps & { onClose: () => void; onConfirmPay: () => void }) => { - const { t } = useTranslation(); - - const [qrPayData, setQRPayData] = useState(); - - const formatPayPrice = Math.ceil(formatStorePrice2Read(payPrice)); - const formatTeamBalance = Math.floor(formatStorePrice2Read(teamBalance)); - - const { mutate: handleClickPay, isLoading } = useRequest({ - mutationFn: async (amount: number) => { - // 获取支付二维码 - return getWxPayQRCode({ - type: BillTypeEnum.balance, - balance: amount - }); - }, - onSuccess(res) { - setQRPayData({ - readPrice: res.readPrice, - codeUrl: res.codeUrl, - billId: res.billId - }); - } - }); - - const { runAsync: onPay, loading: onPaying } = useRequest2(async () => onConfirmPay()); - - return ( - - - - {t('common:pay.new_package_price')} - {t('common:pay.yuan', { amount: formatStorePrice2Read(totalPrice) })} - - - {t('common:pay.old_package_price')} - - {t('common:pay.yuan', { - amount: Math.floor(formatStorePrice2Read(totalPrice - payPrice)) - })} - - - - {t('common:pay.need_to_pay')} - - {t('common:pay.yuan', { - amount: formatPayPrice - })} - - - - - {t('common:pay.balance') + ': '} - - {t('common:pay.yuan', { - amount: formatTeamBalance - })} - - {teamBalance >= payPrice ? ( - - ) : ( - - )} - - - {!!qrPayData && } - - ); -}; diff --git a/projects/app/src/pages/price/index.tsx b/projects/app/src/pages/price/index.tsx index 78add702c..d129aa289 100644 --- a/projects/app/src/pages/price/index.tsx +++ b/projects/app/src/pages/price/index.tsx @@ -1,7 +1,6 @@ import React from 'react'; import { serviceSideProps } from '@/web/common/utils/i18n'; -import { Box, Image } from '@chakra-ui/react'; -import { useTranslation } from 'next-i18next'; +import { Box } 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'; @@ -14,7 +13,6 @@ import { getToken } from '@/web/support/user/auth'; import Script from 'next/script'; const PriceBox = () => { - const { t } = useTranslation(); const { userInfo } = useUserStore(); const { data: teamSubPlan, refetch: refetchTeamSubPlan } = useQuery( @@ -60,6 +58,6 @@ export default PriceBox; export async function getServerSideProps(context: any) { return { - props: { ...(await serviceSideProps(context)) } + props: { ...(await serviceSideProps(context, ['user'])) } }; } diff --git a/projects/app/src/web/support/wallet/sub/api.ts b/projects/app/src/web/support/wallet/sub/api.ts deleted file mode 100644 index 32236cb92..000000000 --- a/projects/app/src/web/support/wallet/sub/api.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { GET, POST, PUT, DELETE } from '@/web/common/api/request'; -import { - StandardSubPlanParams, - StandardSubPlanUpdateResponse -} from '@fastgpt/global/support/wallet/sub/api'; -import { SubStatusEnum, SubTypeEnum } from '@fastgpt/global/support/wallet/sub/constants'; - -export const putTeamDatasetSubStatus = (data: { - status: `${SubStatusEnum}`; - type: `${SubTypeEnum}`; -}) => POST('/proApi/support/wallet/sub/updateStatus', data); - -export const postCheckStandardSub = (data: StandardSubPlanParams) => - POST('/proApi/support/wallet/sub/standard/preCheck', data); -export const postUpdateStandardSub = (data: StandardSubPlanParams) => - POST('/proApi/support/wallet/sub/standard/update', data);