diff --git a/packages/web/components/common/Icon/constants.ts b/packages/web/components/common/Icon/constants.ts index 0b4bafaa2..a94f868d5 100644 --- a/packages/web/components/common/Icon/constants.ts +++ b/packages/web/components/common/Icon/constants.ts @@ -30,9 +30,9 @@ export const iconPaths = { 'common/gitInlight': () => import('./icons/common/gitInlight.svg'), 'common/gitLight': () => import('./icons/common/gitLight.svg'), 'common/googleFill': () => import('./icons/common/googleFill.svg'), + 'common/help': () => import('./icons/common/help.svg'), 'common/importLight': () => import('./icons/common/importLight.svg'), 'common/info': () => import('./icons/common/info.svg'), - 'common/help': () => import('./icons/common/help.svg'), 'common/inviteLight': () => import('./icons/common/inviteLight.svg'), 'common/language/en': () => import('./icons/common/language/en.svg'), 'common/language/zh': () => import('./icons/common/language/zh.svg'), @@ -244,10 +244,7 @@ export const iconPaths = { delete: () => import('./icons/delete.svg'), edit: () => import('./icons/edit.svg'), empty: () => import('./icons/empty.svg'), - paragraph: () => import('./icons/paragraph.svg'), export: () => import('./icons/export.svg'), - point: () => import('./icons/point.svg'), - infoRounded: () => import('./icons/infoRounded.svg'), 'file/csv': () => import('./icons/file/csv.svg'), 'file/fill/csv': () => import('./icons/file/fill/csv.svg'), 'file/fill/doc': () => import('./icons/file/fill/doc.svg'), @@ -268,6 +265,7 @@ export const iconPaths = { 'file/qaImport': () => import('./icons/file/qaImport.svg'), 'file/uploadFile': () => import('./icons/file/uploadFile.svg'), history: () => import('./icons/history.svg'), + infoRounded: () => import('./icons/infoRounded.svg'), kbTest: () => import('./icons/kbTest.svg'), menu: () => import('./icons/menu.svg'), minus: () => import('./icons/minus.svg'), @@ -283,11 +281,13 @@ export const iconPaths = { more: () => import('./icons/more.svg'), moreLine: () => import('./icons/moreLine.svg'), out: () => import('./icons/out.svg'), + paragraph: () => import('./icons/paragraph.svg'), 'phoneTabbar/me': () => import('./icons/phoneTabbar/me.svg'), 'phoneTabbar/tool': () => import('./icons/phoneTabbar/tool.svg'), 'phoneTabbar/toolFill': () => import('./icons/phoneTabbar/toolFill.svg'), 'plugins/doc2x': () => import('./icons/plugins/doc2x.svg'), 'plugins/textEditor': () => import('./icons/plugins/textEditor.svg'), + point: () => import('./icons/point.svg'), 'price/bg': () => import('./icons/price/bg.svg'), 'price/right': () => import('./icons/price/right.svg'), save: () => import('./icons/save.svg'), @@ -301,6 +301,7 @@ export const iconPaths = { 'support/bill/payRecordLight': () => import('./icons/support/bill/payRecordLight.svg'), 'support/bill/priceLight': () => import('./icons/support/bill/priceLight.svg'), 'support/bill/shoppingCart': () => import('./icons/support/bill/shoppingCart.svg'), + 'support/bill/wallet': () => import('./icons/support/bill/wallet.svg'), 'support/outlink/apikeyFill': () => import('./icons/support/outlink/apikeyFill.svg'), 'support/outlink/apikeyLight': () => import('./icons/support/outlink/apikeyLight.svg'), 'support/outlink/iframeLight': () => import('./icons/support/outlink/iframeLight.svg'), diff --git a/packages/web/components/common/Icon/icons/support/bill/wallet.svg b/packages/web/components/common/Icon/icons/support/bill/wallet.svg new file mode 100644 index 000000000..1261d5dd0 --- /dev/null +++ b/packages/web/components/common/Icon/icons/support/bill/wallet.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/packages/web/components/common/MyModal/index.tsx b/packages/web/components/common/MyModal/index.tsx index 9c9988ef0..e0f3fd0c6 100644 --- a/packages/web/components/common/MyModal/index.tsx +++ b/packages/web/components/common/MyModal/index.tsx @@ -14,6 +14,7 @@ import Avatar from '../Avatar'; export interface MyModalProps extends ModalContentProps { iconSrc?: string; + iconColor?: string; title?: any; isCentered?: boolean; isLoading?: boolean; @@ -33,6 +34,7 @@ const MyModal = ({ w = 'auto', maxW = ['90vw', '600px'], closeOnOverlayClick = true, + iconColor, ...props }: MyModalProps) => { const { isPc } = useSystem(); @@ -71,6 +73,7 @@ const MyModal = ({ {iconSrc && ( <> void; + balance: string; + tokens: string; + onOpenContact: () => void; +}) => { + const { t } = useTranslation(); + + const { runAsync: onConvert, loading } = useRequest2(balanceConversion, { + successToast: t('user:bill.convert_success'), + errorToast: t('user:bill.convert_error') + }); + + return ( + + + {loading && } + + + + {t('user:bill.use_balance_hint')} + + + + {t('user:bill.price')} + + + ¥15/1000 {t('user:bill.tokens')} + + + + + {t('user:bill.balance')} + + + ¥{balance} + + + + + {t('user:bill.you_can_convert')} + + + {tokens} {t('user:bill.tokens')} + + {t('user:bill.token_expire_1year')} + + + + + + {t('user:bill.contact_customer_service')} + + + + + + ); +}; + +export default ConversionModal; diff --git a/projects/app/src/pages/account/components/Info.tsx b/projects/app/src/pages/account/components/Info.tsx index 8a832c476..d9bc8094f 100644 --- a/projects/app/src/pages/account/components/Info.tsx +++ b/projects/app/src/pages/account/components/Info.tsx @@ -48,7 +48,7 @@ import { useSystem } from '@fastgpt/web/hooks/useSystem'; const StandDetailModal = dynamic(() => import('./standardDetailModal')); const TeamMenu = dynamic(() => import('@/components/support/user/team/TeamMenu')); -const PayModal = dynamic(() => import('./PayModal')); +const ConversionModal = dynamic(() => import('./ConversionModal')); const UpdatePswModal = dynamic(() => import('./UpdatePswModal')); const UpdateNotification = dynamic(() => import('./UpdateNotificationModal')); const OpenAIAccountModal = dynamic(() => import('./OpenAIAccountModal')); @@ -59,41 +59,45 @@ const Account = () => { const { isPc } = useSystem(); const { teamPlanStatus } = useUserStore(); const standardPlan = teamPlanStatus?.standardConstants; + const { isOpen: isOpenContact, onClose: onCloseContact, onOpen: onOpenContact } = useDisclosure(); const { initUserInfo } = useUserStore(); useQuery(['init'], initUserInfo); return ( - - {isPc ? ( - - - - - + <> + + {isPc ? ( + + + + + + - - {!!standardPlan && ( - - - - )} - - ) : ( - <> - - {standardPlan && } - - - )} - + {!!standardPlan && ( + + + + )} + + ) : ( + <> + + {standardPlan && } + + + )} + + {isOpenContact && } + ); }; export default React.memo(Account); -const MyInfo = () => { +const MyInfo = ({ onOpenContact }: { onOpenContact: () => void }) => { const theme = useTheme(); const { feConfigs } = useSystemStore(); const { t } = useTranslation(); @@ -101,13 +105,14 @@ const MyInfo = () => { const { reset } = useForm({ defaultValues: userInfo as UserType }); + const { teamPlanStatus } = useUserStore(); + const standardPlan = teamPlanStatus?.standardConstants; const { isPc } = useSystem(); - const { toast } = useToast(); const { - isOpen: isOpenPayModal, - onClose: onClosePayModal, - onOpen: onOpenPayModal + isOpen: isOpenConversionModal, + onClose: onCloseConversionModal, + onOpen: onOpenConversionModal } = useDisclosure(); const { isOpen: isOpenUpdatePsw, @@ -293,23 +298,30 @@ const MyInfo = () => { - {feConfigs?.isPlus && ( + {feConfigs?.isPlus && (userInfo?.team?.balance ?? 0) > 0 && ( {t('common:user.team.Balance')}:  {formatStorePrice2Read(userInfo?.team?.balance).toFixed(3)} - {feConfigs?.show_pay && userInfo?.team?.permission.hasWritePer && ( - )} )} - {isOpenPayModal && } + {isOpenConversionModal && ( + + )} {isOpenUpdatePsw && } {isOpenUpdateNotification && } @@ -552,7 +564,8 @@ const PlanUsage = () => { ) : null; }; -const Other = () => { + +const Other = ({ onOpenContact }: { onOpenContact: () => void }) => { const theme = useTheme(); const { toast } = useToast(); const { feConfigs } = useSystemStore(); @@ -563,7 +576,6 @@ const Other = () => { }); const { isOpen: isOpenLaf, onClose: onCloseLaf, onOpen: onOpenLaf } = useDisclosure(); const { isOpen: isOpenOpenai, onClose: onCloseOpenai, onOpen: onOpenOpenai } = useDisclosure(); - const { isOpen: isOpenConcat, onClose: onCloseConcat, onOpen: onOpenConcat } = useDisclosure(); const onclickSave = useCallback( async (data: UserType) => { @@ -686,7 +698,7 @@ const Other = () => { variant={'whiteBase'} justifyContent={'flex-start'} leftIcon={} - onClick={onOpenConcat} + onClick={onOpenContact} h={'48px'} fontSize={'sm'} > @@ -710,7 +722,6 @@ const Other = () => { onClose={onCloseOpenai} /> )} - {isOpenConcat && } ); }; diff --git a/projects/app/src/web/support/wallet/bill/api.ts b/projects/app/src/web/support/wallet/bill/api.ts index d6dc86700..ce178f38a 100644 --- a/projects/app/src/web/support/wallet/bill/api.ts +++ b/projects/app/src/web/support/wallet/bill/api.ts @@ -20,3 +20,5 @@ export const checkBalancePayResult = (payId: string) => } catch (error) {} return data; }); + +export const balanceConversion = () => GET(`/proApi/support/wallet/bill/balanceConversion`);