mirror of
https://github.com/labring/FastGPT.git
synced 2025-10-13 22:56:28 +00:00
feat: enhance wallet billing features (#5293)
* feat: enhance wallet billing features with new dataset and points options * chore: removed local state for dataset month and replaced it with form state management * chore: remove redundant state
This commit is contained in:
1
packages/global/support/wallet/bill/api.d.ts
vendored
1
packages/global/support/wallet/bill/api.d.ts
vendored
@@ -16,6 +16,7 @@ export type CreateStandPlanBill = {
|
||||
type CreateExtractPointsBill = {
|
||||
type: BillTypeEnum.extraPoints;
|
||||
extraPoints: number;
|
||||
month: number;
|
||||
};
|
||||
type CreateExtractDatasetBill = {
|
||||
type: BillTypeEnum.extraDatasetSub;
|
||||
|
37
packages/global/support/wallet/bill/tools.ts
Normal file
37
packages/global/support/wallet/bill/tools.ts
Normal file
@@ -0,0 +1,37 @@
|
||||
import type { PriceOption } from './type';
|
||||
|
||||
// 根据积分获取月份
|
||||
export const getMonthByPoints = (points: number) => {
|
||||
if (points >= 200) return 12;
|
||||
if (points >= 100) return 6;
|
||||
if (points >= 50) return 3;
|
||||
return 1;
|
||||
};
|
||||
|
||||
// 根据月份获取积分下限
|
||||
export const getMinPointsByMonth = (month: number): number => {
|
||||
switch (month) {
|
||||
case 12:
|
||||
return 200;
|
||||
case 6:
|
||||
return 100;
|
||||
case 3:
|
||||
return 50;
|
||||
case 1:
|
||||
return 1;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
|
||||
// 计算额外资源包的所需付款价格
|
||||
export const calculatePrice = (unitPrice: number, option: PriceOption) => {
|
||||
switch (option.type) {
|
||||
case 'points':
|
||||
return unitPrice * option.points * 1;
|
||||
case 'dataset':
|
||||
return unitPrice * option.size * option.month;
|
||||
default:
|
||||
throw new Error('Invalid price option type');
|
||||
}
|
||||
};
|
13
packages/global/support/wallet/bill/type.d.ts
vendored
13
packages/global/support/wallet/bill/type.d.ts
vendored
@@ -50,3 +50,16 @@ export type InvoiceSchemaType = {
|
||||
finishTime?: Date;
|
||||
file?: Buffer;
|
||||
} & InvoiceType;
|
||||
|
||||
export type AIPointsPriceOption = {
|
||||
type: 'points';
|
||||
points: number;
|
||||
};
|
||||
|
||||
export type DatasetPriceOption = {
|
||||
type: 'dataset';
|
||||
size: number;
|
||||
month: number;
|
||||
};
|
||||
|
||||
export type PriceOption = AIPointsPriceOption | DatasetPriceOption;
|
||||
|
@@ -74,6 +74,7 @@ export const menuItemStyles: MenuItemProps = {
|
||||
|
||||
const MySelect = <T = any,>(
|
||||
{
|
||||
bg = '#fff',
|
||||
placeholder,
|
||||
value,
|
||||
valueLabel,
|
||||
@@ -223,6 +224,7 @@ const MySelect = <T = any,>(
|
||||
_active={{
|
||||
transform: 'none'
|
||||
}}
|
||||
bg={bg ? (isOpen ? '#fff' : bg) : '#fff'}
|
||||
color={isOpen ? 'primary.700' : 'myGray.700'}
|
||||
borderColor={isInvalid ? 'red.500' : isOpen ? 'primary.300' : 'myGray.200'}
|
||||
boxShadow={
|
||||
@@ -232,17 +234,7 @@ const MySelect = <T = any,>(
|
||||
: '0px 0px 0px 2.4px rgba(51, 112, 255, 0.15)'
|
||||
: 'none'
|
||||
}
|
||||
_hover={
|
||||
isInvalid
|
||||
? {
|
||||
borderColor: 'red.400',
|
||||
boxShadow: '0px 0px 0px 2.4px rgba(255, 0, 0, 0.15)'
|
||||
}
|
||||
: {
|
||||
borderColor: 'primary.300',
|
||||
boxShadow: '0px 0px 0px 2.4px rgba(51, 112, 255, 0.15)'
|
||||
}
|
||||
}
|
||||
_hover={isInvalid ? { borderColor: 'red.400' } : { borderColor: 'primary.300' }}
|
||||
{...props}
|
||||
>
|
||||
<Flex alignItems={'center'} justifyContent="space-between" w="100%">
|
||||
|
@@ -469,7 +469,7 @@
|
||||
"core.dataset.data.Search data placeholder": "Search Related Data",
|
||||
"core.dataset.data.Too Long": "Total Length Exceeded",
|
||||
"core.dataset.data.Updated": "Updated",
|
||||
"core.dataset.data.group": "Group",
|
||||
"core.dataset.data.group": " Groups",
|
||||
"core.dataset.data.unit": "Items",
|
||||
"core.dataset.embedding model tip": "The index model can convert natural language into vectors for semantic search.\nNote that different index models cannot be used together. Once an index model is selected, it cannot be changed.",
|
||||
"core.dataset.error.Data not found": "Data Not Found or Deleted",
|
||||
@@ -1119,6 +1119,8 @@
|
||||
"support.wallet.bill_tag.default_header": "Default Header",
|
||||
"support.wallet.bill_tag.invoice": "Invoice Records",
|
||||
"support.wallet.billable_invoice": "Billable Invoice",
|
||||
"support.wallet.buy_ai_points": "Buy AI points",
|
||||
"support.wallet.buy_dataset_capacity": "Buy Knowledge Base Index",
|
||||
"support.wallet.buy_resource": "Buy Resource Pack",
|
||||
"support.wallet.has_invoice": "Invoiced",
|
||||
"support.wallet.invoice_amount": "Invoice Amount",
|
||||
@@ -1142,20 +1144,33 @@
|
||||
"support.wallet.subscription.AI points usage tip": "Each time the AI model is called, a certain amount of AI points will be consumed. For specific calculation standards, please refer to the 'Pricing' above.",
|
||||
"support.wallet.subscription.Ai points": "AI Points Calculation Standards",
|
||||
"support.wallet.subscription.Current plan": "Current Package",
|
||||
"support.wallet.subscription.Extra ai points": "AI points",
|
||||
"support.wallet.subscription.Dataset size": "Knowledge Base Index",
|
||||
"support.wallet.subscription.Extra ai points": "AI Points",
|
||||
"support.wallet.subscription.Extra ai points description": "The purchase amount of points is intelligently linked to the validity period. The more you buy, the longer you use it.",
|
||||
"support.wallet.subscription.Extra dataset description": "Supports extending the validity period for the knowledge base index based on actual needs",
|
||||
"support.wallet.subscription.Extra dataset size": "Extra Dataset Capacity",
|
||||
"support.wallet.subscription.Extra dataset unit": " Groups/1 Month",
|
||||
"support.wallet.subscription.Extra plan": "Extra Resource Pack",
|
||||
"support.wallet.subscription.Extra plan tip": "When the standard package is not enough, you can purchase extra resource packs to continue using",
|
||||
"support.wallet.subscription.FAQ": "FAQ",
|
||||
"support.wallet.subscription.Month amount": "Months",
|
||||
"support.wallet.subscription.Next plan": "Future Package",
|
||||
"support.wallet.subscription.Points amount": "AI Points",
|
||||
"support.wallet.subscription.Stand plan level": "Subscription Package",
|
||||
"support.wallet.subscription.Sub plan": "Subscription Package",
|
||||
"support.wallet.subscription.Sub plan tip": "Free to use [{{title}}] or upgrade to a higher package",
|
||||
"support.wallet.subscription.Team plan and usage": "Package and Usage",
|
||||
"support.wallet.subscription.Training weight": "Training Priority: {{weight}}",
|
||||
"support.wallet.subscription.Update extra ai points": "Extra AI Points",
|
||||
"support.wallet.subscription.Update extra ai points tips": "Purchase points will take effect immediately and will automatically expire after expiration.",
|
||||
"support.wallet.subscription.Update extra dataset size": "Storage",
|
||||
"support.wallet.subscription.Update extra dataset tips": "After the knowledge base index expires, the existing data is still retained and the data cannot be added or modified.",
|
||||
"support.wallet.subscription.Update extra expire": "Validity period",
|
||||
"support.wallet.subscription.Update extra expire 1 month": "1 Month",
|
||||
"support.wallet.subscription.Update extra expire 12 months": "12 Months",
|
||||
"support.wallet.subscription.Update extra expire 3 months": "3 Months",
|
||||
"support.wallet.subscription.Update extra expire 6 months": "6 Months",
|
||||
"support.wallet.subscription.Update extra price": "Price",
|
||||
"support.wallet.subscription.Upgrade plan": "Upgrade Package",
|
||||
"support.wallet.subscription.ai_model": "AI Language Model",
|
||||
"support.wallet.subscription.function.History store": "{{amount}} Days of Chat History Retention",
|
||||
@@ -1168,7 +1183,7 @@
|
||||
"support.wallet.subscription.mode.Period": "Subscription Period",
|
||||
"support.wallet.subscription.mode.Year": "Year",
|
||||
"support.wallet.subscription.mode.Year sale": "Two Months Free",
|
||||
"support.wallet.subscription.point": "Points",
|
||||
"support.wallet.subscription.point": " Points",
|
||||
"support.wallet.subscription.standardSubLevel.custom": "Custom",
|
||||
"support.wallet.subscription.standardSubLevel.enterprise": "Enterprise",
|
||||
"support.wallet.subscription.standardSubLevel.enterprise_desc": "Suitable for small and medium-sized enterprises to build Dataset applications in production environments",
|
||||
|
@@ -1143,6 +1143,7 @@
|
||||
"support.wallet.subscription.Ai points": "AI 积分计算标准",
|
||||
"support.wallet.subscription.Current plan": "当前套餐",
|
||||
"support.wallet.subscription.Extra ai points": "额外 AI 积分",
|
||||
"support.wallet.subscription.Extra ai points description": "积分购买量与有效期智能联动, 买的越多用的越久",
|
||||
"support.wallet.subscription.Extra dataset size": "额外知识库容量",
|
||||
"support.wallet.subscription.Extra plan": "额外资源包",
|
||||
"support.wallet.subscription.Extra plan tip": "标准套餐不够时,您可以购买额外资源包继续使用",
|
||||
@@ -1156,6 +1157,20 @@
|
||||
"support.wallet.subscription.Training weight": "训练优先级:{{weight}}",
|
||||
"support.wallet.subscription.Update extra ai points": "额外 AI 积分",
|
||||
"support.wallet.subscription.Update extra dataset size": "额外存储量",
|
||||
"support.wallet.subscription.Update extra expire 1 month": "1个月",
|
||||
"support.wallet.subscription.Update extra expire 12 months": "12个月",
|
||||
"support.wallet.subscription.Update extra expire 3 months": "3个月",
|
||||
"support.wallet.subscription.Update extra expire 6 months": "6个月",
|
||||
"support.wallet.buy_ai_points": "购买 AI 积分",
|
||||
"support.wallet.subscription.Update extra expire": "有效期",
|
||||
"support.wallet.subscription.Update extra price": "价格",
|
||||
"support.wallet.subscription.Update extra dataset tips": "知识库索引量到期后,仍保留已有数据,无法增改数据",
|
||||
"support.wallet.subscription.Dataset size": "知识库索引量",
|
||||
"support.wallet.buy_dataset_capacity": "购买知识库索引量",
|
||||
"support.wallet.subscription.Extra dataset description": "支持根据实际需求为知识库索引量延长有效期",
|
||||
"support.wallet.subscription.Extra dataset unit": "组/1个月",
|
||||
"support.wallet.subscription.Update extra ai points tips": "购买积分即刻生效,过期后将自动失效",
|
||||
"support.wallet.subscription.Points amount": "积分量",
|
||||
"support.wallet.subscription.Upgrade plan": "升级套餐",
|
||||
"support.wallet.subscription.ai_model": "AI语言模型",
|
||||
"support.wallet.subscription.eval_items_count": "单次评测数据条数: {{count}} 条",
|
||||
|
@@ -1119,6 +1119,8 @@
|
||||
"support.wallet.bill_tag.default_header": "預設抬頭",
|
||||
"support.wallet.bill_tag.invoice": "發票紀錄",
|
||||
"support.wallet.billable_invoice": "可開立發票的帳單",
|
||||
"support.wallet.buy_ai_points": "購買 AI 積分",
|
||||
"support.wallet.buy_dataset_capacity": "購買知識庫索引量",
|
||||
"support.wallet.buy_resource": "購買資源包",
|
||||
"support.wallet.has_invoice": "已開立發票",
|
||||
"support.wallet.invoice_amount": "發票金額",
|
||||
@@ -1142,20 +1144,33 @@
|
||||
"support.wallet.subscription.AI points usage tip": "每次呼叫 AI 模型時,都會消耗一定的 AI 點數。具體的計算標準可參考上方的「計費標準」",
|
||||
"support.wallet.subscription.Ai points": "AI 點數計算標準",
|
||||
"support.wallet.subscription.Current plan": "目前方案",
|
||||
"support.wallet.subscription.Dataset size": "知識庫索引量",
|
||||
"support.wallet.subscription.Extra ai points": "額外 AI 點數",
|
||||
"support.wallet.subscription.Extra ai points description": "積分購買量與有效期智能聯動, 買的越多用的越久",
|
||||
"support.wallet.subscription.Extra dataset description": "支持根據實際需求為知識庫索引量延長有效期",
|
||||
"support.wallet.subscription.Extra dataset size": "額外知識庫容量",
|
||||
"support.wallet.subscription.Extra dataset unit": "組/1個月",
|
||||
"support.wallet.subscription.Extra plan": "額外資源包",
|
||||
"support.wallet.subscription.Extra plan tip": "當標準方案不足時,您可以購買額外資源包繼續使用",
|
||||
"support.wallet.subscription.FAQ": "常見問題",
|
||||
"support.wallet.subscription.Month amount": "月數",
|
||||
"support.wallet.subscription.Next plan": "未來方案",
|
||||
"support.wallet.subscription.Points amount": "積分量",
|
||||
"support.wallet.subscription.Stand plan level": "訂閱方案",
|
||||
"support.wallet.subscription.Sub plan": "訂閱方案",
|
||||
"support.wallet.subscription.Sub plan tip": "免費使用【{{title}}】或升級更進階的方案",
|
||||
"support.wallet.subscription.Team plan and usage": "方案與使用量",
|
||||
"support.wallet.subscription.Training weight": "訓練優先權:{{weight}}",
|
||||
"support.wallet.subscription.Update extra ai points": "額外 AI 點數",
|
||||
"support.wallet.subscription.Update extra ai points tips": "購買積分即刻生效,過期後將自動失效",
|
||||
"support.wallet.subscription.Update extra dataset size": "額外儲存空間",
|
||||
"support.wallet.subscription.Update extra dataset tips": "知識庫索引量到期後,仍保留已有數據,無法增改數據",
|
||||
"support.wallet.subscription.Update extra expire": "有效期",
|
||||
"support.wallet.subscription.Update extra expire 1 month": "1個月",
|
||||
"support.wallet.subscription.Update extra expire 12 months": "12個月",
|
||||
"support.wallet.subscription.Update extra expire 3 months": "3個月",
|
||||
"support.wallet.subscription.Update extra expire 6 months": "6個月",
|
||||
"support.wallet.subscription.Update extra price": "價格",
|
||||
"support.wallet.subscription.Upgrade plan": "升級方案",
|
||||
"support.wallet.subscription.ai_model": "AI 語言模型",
|
||||
"support.wallet.subscription.function.History store": "{{amount}} 天對話紀錄保留",
|
||||
|
@@ -244,14 +244,8 @@ export const LoginContainer = ({
|
||||
|
||||
<Box position="relative" w="full" h="full">
|
||||
{/* main content area */}
|
||||
<Box w={['100%', '380px']} flex={'1 0 0'}>
|
||||
{pageType && DynamicComponent ? (
|
||||
DynamicComponent
|
||||
) : (
|
||||
<Center w={'full'} h={'full'} position={'relative'}>
|
||||
<Loading fixed={false} />
|
||||
</Center>
|
||||
)}
|
||||
<Box w={['100%', '380px']} minH={['100vh', '600px']} flex={'1 0 0'}>
|
||||
{pageType && DynamicComponent ? DynamicComponent : <Loading fixed={false} />}
|
||||
</Box>
|
||||
|
||||
{/* custom content */}
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import { Box, Flex, Grid, Button, VStack } from '@chakra-ui/react';
|
||||
import { Box, Flex, Grid, Button, VStack, HStack } from '@chakra-ui/react';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import React, { useState } from 'react';
|
||||
import { useSystemStore } from '@/web/common/system/useSystemStore';
|
||||
@@ -10,6 +10,12 @@ 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';
|
||||
import { useRequest2 } from '@fastgpt/web/hooks/useRequest';
|
||||
import MySelect from '@fastgpt/web/components/common/MySelect';
|
||||
import {
|
||||
getMonthByPoints,
|
||||
getMinPointsByMonth,
|
||||
calculatePrice
|
||||
} from '@fastgpt/global/support/wallet/bill/tools';
|
||||
|
||||
const ExtraPlan = ({ onPaySuccess }: { onPaySuccess?: () => void }) => {
|
||||
const { t } = useTranslation();
|
||||
@@ -17,14 +23,30 @@ const ExtraPlan = ({ onPaySuccess }: { onPaySuccess?: () => void }) => {
|
||||
const { subPlans } = useSystemStore();
|
||||
const [qrPayData, setQRPayData] = useState<QRPayProps>();
|
||||
|
||||
// extra dataset
|
||||
const expireSelectorOptions: { label: string; value: number }[] = [
|
||||
{ label: t('common:support.wallet.subscription.Update extra expire 1 month'), value: 1 },
|
||||
{ label: t('common:support.wallet.subscription.Update extra expire 3 months'), value: 3 },
|
||||
{ label: t('common:support.wallet.subscription.Update extra expire 6 months'), value: 6 },
|
||||
{ label: t('common:support.wallet.subscription.Update extra expire 12 months'), value: 12 }
|
||||
];
|
||||
|
||||
// 额外的知识库索引量
|
||||
const extraDatasetPrice = subPlans?.extraDatasetSize?.price || 0;
|
||||
const { register: registerDatasetSize, handleSubmit: handleSubmitDatasetSize } = useForm({
|
||||
const {
|
||||
watch: watchDatasetSize,
|
||||
register: registerDatasetSize,
|
||||
handleSubmit: handleSubmitDatasetSize,
|
||||
setValue: setValueDatasetSize
|
||||
} = useForm({
|
||||
defaultValues: {
|
||||
datasetSize: 0,
|
||||
datasetSize: 1,
|
||||
month: 1
|
||||
}
|
||||
});
|
||||
|
||||
const watchedDatasetSize = watchDatasetSize('datasetSize');
|
||||
const watchedDatasetMonth = watchDatasetSize('month');
|
||||
|
||||
const { runAsync: onclickBuyDatasetSize, loading: isLoadingBuyDatasetSize } = useRequest2(
|
||||
async ({ datasetSize, month }: { datasetSize: number; month: number }) => {
|
||||
datasetSize = Math.ceil(datasetSize);
|
||||
@@ -56,18 +78,27 @@ const ExtraPlan = ({ onPaySuccess }: { onPaySuccess?: () => void }) => {
|
||||
|
||||
// extra ai points
|
||||
const extraPointsPrice = subPlans?.extraPoints?.price || 0;
|
||||
const { register: registerExtraPoints, handleSubmit: handleSubmitExtraPoints } = useForm({
|
||||
const {
|
||||
watch: watchExtraPoints,
|
||||
setValue: setValueExtraPoints,
|
||||
getValues: getValuesExtraPoints
|
||||
} = useForm({
|
||||
defaultValues: {
|
||||
points: 0,
|
||||
points: 1,
|
||||
month: 1
|
||||
}
|
||||
});
|
||||
const { runAsync: onclickBuyExtraPoints, loading: isLoadingBuyExtraPoints } = useRequest2(
|
||||
async ({ points }: { points: number }) => {
|
||||
points = Math.ceil(points);
|
||||
|
||||
const month = 1;
|
||||
const payAmount = points * month * extraPointsPrice;
|
||||
// 监听积分和月份变化
|
||||
const watchedPoints = watchExtraPoints('points');
|
||||
const watchedMonth = watchExtraPoints('month');
|
||||
|
||||
const { runAsync: onclickBuyExtraPoints, loading: isLoadingBuyExtraPoints } = useRequest2(
|
||||
async ({ points, month }: { points: number; month: number }) => {
|
||||
points = Math.ceil(points);
|
||||
month = Math.ceil(month);
|
||||
|
||||
const payAmount = points * 1 * extraPointsPrice;
|
||||
|
||||
if (payAmount === 0) {
|
||||
return toast({
|
||||
@@ -78,6 +109,7 @@ const ExtraPlan = ({ onPaySuccess }: { onPaySuccess?: () => void }) => {
|
||||
|
||||
const res = await postCreatePayBill({
|
||||
type: BillTypeEnum.extraPoints,
|
||||
month,
|
||||
extraPoints: points
|
||||
});
|
||||
|
||||
@@ -95,89 +127,9 @@ const ExtraPlan = ({ onPaySuccess }: { onPaySuccess?: () => void }) => {
|
||||
return (
|
||||
<VStack>
|
||||
<Grid gridTemplateColumns={['1fr', '1fr 1fr']} gap={5} w={['100%', 'auto']}>
|
||||
<Box
|
||||
bg={'rgba(255, 255, 255, 0.90)'}
|
||||
px={'32px'}
|
||||
py={'24px'}
|
||||
borderRadius={'2xl'}
|
||||
borderWidth={'1px'}
|
||||
borderColor={'myGray.150'}
|
||||
boxShadow={'1.5'}
|
||||
w={['100%', '500px']}
|
||||
>
|
||||
<Flex borderBottomWidth={'1px'} borderBottomColor={'myGray.200'}>
|
||||
<Box flex={'1 0 0'}>
|
||||
<Box fontSize={'lg'} color={'primary.700'}>
|
||||
{t('common:support.wallet.subscription.Extra dataset size')}
|
||||
</Box>
|
||||
<Box mt={3} fontSize={['28px', '32px']} fontWeight={'bold'} color={'black'}>
|
||||
{`¥${extraDatasetPrice}/1000` + t('common:core.dataset.data.group')}
|
||||
<Box ml={1} as={'span'} fontSize={'md'} color={'myGray.500'} fontWeight={'normal'}>
|
||||
/{t('common:month')}
|
||||
</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
<MyIcon
|
||||
display={['none', 'block']}
|
||||
mt={'-30px'}
|
||||
transform={'translateX(20px)'}
|
||||
name={'support/bill/extraDatasetsize'}
|
||||
fill={'none'}
|
||||
/>
|
||||
</Flex>
|
||||
<Box h={'120px'} w={'100%'}>
|
||||
<Flex mt={4} color={'myGray.900'}>
|
||||
<MyIcon mr={2} name={'support/bill/shoppingCart'} w={'16px'} color={'primary.600'} />
|
||||
{t('common:support.wallet.buy_resource')}
|
||||
</Flex>
|
||||
<Flex mt={4} alignItems={'center'}>
|
||||
<Box flex={['0 0 100px', '1 0 0']} color={'myGray.600'}>
|
||||
{t('common:support.wallet.subscription.Month amount')}
|
||||
</Box>
|
||||
<Flex alignItems={'center'} mt={1} w={'180px'} position={'relative'}>
|
||||
<MyNumberInput
|
||||
name="month"
|
||||
register={registerDatasetSize}
|
||||
min={1}
|
||||
max={12}
|
||||
size={'sm'}
|
||||
/>
|
||||
<Box position={'absolute'} right={'30px'} color={'myGray.600'} fontSize={'xs'}>
|
||||
{t('common:month')}
|
||||
</Box>
|
||||
</Flex>
|
||||
</Flex>
|
||||
<Flex mt={4} alignItems={'center'}>
|
||||
<Box flex={['0 0 100px', '1 0 0']} color={'myGray.600'}>
|
||||
{t('common:support.wallet.subscription.Update extra dataset size')}
|
||||
</Box>
|
||||
<Flex alignItems={'center'} mt={1} w={'180px'} position={'relative'}>
|
||||
<MyNumberInput
|
||||
name="datasetSize"
|
||||
register={registerDatasetSize}
|
||||
min={0}
|
||||
max={10000}
|
||||
size={'sm'}
|
||||
/>
|
||||
<Box position={'absolute'} right={'30px'} color={'myGray.600'} fontSize={'xs'}>
|
||||
000{t('common:core.dataset.data.unit')}
|
||||
</Box>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</Box>
|
||||
<Button
|
||||
mt={6}
|
||||
w={'100%'}
|
||||
variant={'primaryGhost'}
|
||||
isLoading={isLoadingBuyDatasetSize}
|
||||
onClick={handleSubmitDatasetSize(onclickBuyDatasetSize)}
|
||||
color={'primary.700'}
|
||||
>
|
||||
{t('common:support.wallet.Buy')}
|
||||
</Button>
|
||||
</Box>
|
||||
{/* points */}
|
||||
<Box
|
||||
<Flex
|
||||
flexDir="column"
|
||||
bg={'rgba(255, 255, 255, 0.90)'}
|
||||
w={['100%', '500px']}
|
||||
px={'32px'}
|
||||
@@ -186,19 +138,20 @@ const ExtraPlan = ({ onPaySuccess }: { onPaySuccess?: () => void }) => {
|
||||
borderWidth={'1px'}
|
||||
borderColor={'myGray.150'}
|
||||
boxShadow={'1.5'}
|
||||
gap={4}
|
||||
>
|
||||
<Flex borderBottomWidth={'1px'} borderBottomColor={'myGray.200'}>
|
||||
<Box flex={'1 0 0'}>
|
||||
<Box fontSize={'lg'} color={'primary.700'}>
|
||||
<Flex borderBottomWidth={'1px'} borderBottomColor={'myGray.200'} pb={1}>
|
||||
<Flex flexDir="column" gap={3} flex={'1 0 0'}>
|
||||
<Box fontSize={'lg'} fontWeight={'500'} color={'primary.700'}>
|
||||
{t('common:support.wallet.subscription.Extra ai points')}
|
||||
</Box>
|
||||
<Box mt={3} fontSize={['28px', '32px']} fontWeight={'bold'} color={'black'}>
|
||||
<Box fontSize={['28px', '32px']} fontWeight={'bold'} color={'black'}>
|
||||
{`¥${extraPointsPrice}/1000` + t('common:support.wallet.subscription.point')}
|
||||
<Box ml={1} as={'span'} fontSize={'md'} color={'myGray.500'} fontWeight={'normal'}>
|
||||
/{t('common:month')}
|
||||
</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
<Box mt="auto" fontSize={'xs'} color={'myGray.600'} fontWeight={'500'}>
|
||||
{t('common:support.wallet.subscription.Extra ai points description')}
|
||||
</Box>
|
||||
</Flex>
|
||||
<MyIcon
|
||||
display={['none', 'block']}
|
||||
mt={'-30px'}
|
||||
@@ -207,55 +160,257 @@ const ExtraPlan = ({ onPaySuccess }: { onPaySuccess?: () => void }) => {
|
||||
fill={'none'}
|
||||
/>
|
||||
</Flex>
|
||||
<Box h={'120px'} w={'100%'}>
|
||||
<Flex mt={4} color={'myGray.900'}>
|
||||
<MyIcon mr={2} name={'support/bill/shoppingCart'} w={'16px'} color={'primary.600'} />
|
||||
{t('common:support.wallet.buy_resource')}
|
||||
<Flex flexDir="column" gap={4} h={'180px'} w={'100%'}>
|
||||
<Flex color={'myGray.900'}>
|
||||
<MyIcon
|
||||
mr={2}
|
||||
name={'support/bill/shoppingCart'}
|
||||
fontWeight={'500'}
|
||||
w={'16px'}
|
||||
color={'primary.600'}
|
||||
/>
|
||||
{t('common:support.wallet.buy_ai_points')}
|
||||
</Flex>
|
||||
<Flex mt={4} alignItems={'center'}>
|
||||
<Box flex={['0 0 100px', '1 0 0']} color={'myGray.600'}>
|
||||
{t('common:support.wallet.subscription.Month amount')}
|
||||
</Box>
|
||||
<Flex alignItems={'center'} mt={1} w={'180px'} position={'relative'}>
|
||||
<Box>1</Box>
|
||||
<Box color={'myGray.600'}>{t('common:month')}</Box>
|
||||
</Flex>
|
||||
</Flex>
|
||||
<Flex mt={4} alignItems={'center'}>
|
||||
<Box flex={['0 0 100px', '1 0 0']} color={'myGray.600'}>
|
||||
{t('common:support.wallet.subscription.Update extra ai points')}
|
||||
<Flex alignItems={'center'} fontSize={'sm'} h="36px">
|
||||
<Box flex={['0 0 100px', '1 0 0']} color={'myGray.600'} fontWeight={'500'}>
|
||||
{t('common:support.wallet.subscription.Points amount')}
|
||||
</Box>
|
||||
<Flex
|
||||
justifyContent={'end'}
|
||||
alignItems={'center'}
|
||||
mt={1}
|
||||
w={'180px'}
|
||||
position={'relative'}
|
||||
color={'myGray.500'}
|
||||
>
|
||||
<MyNumberInput
|
||||
name="points"
|
||||
register={registerExtraPoints}
|
||||
min={0}
|
||||
value={watchedPoints}
|
||||
max={10000}
|
||||
min={0}
|
||||
size={'sm'}
|
||||
onChange={(val) => {
|
||||
// 过滤掉NaN和无效输入
|
||||
if (val === ('' as unknown as number) || val === null || val === undefined) {
|
||||
setValueExtraPoints('points', undefined as unknown as number);
|
||||
} else if (!isNaN(val) && val >= 0) {
|
||||
setValueExtraPoints('points', val as unknown as number);
|
||||
// 当用户输入积分时,自动更新月份
|
||||
const expectedMonth = getMonthByPoints(val);
|
||||
if (expectedMonth !== watchedMonth) {
|
||||
setValueExtraPoints('month', expectedMonth);
|
||||
}
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<Box position={'absolute'} right={'30px'} color={'myGray.500'} fontSize={'xs'}>
|
||||
{'000' + t('common:support.wallet.subscription.point')}
|
||||
<Box flexShrink={0} color={'myGray.600'}>
|
||||
{`X 1000${t('common:support.wallet.subscription.point')}`}
|
||||
</Box>
|
||||
</Flex>
|
||||
</Flex>
|
||||
<Flex alignItems={'center'} fontSize={'sm'} h="36px">
|
||||
<Box flex={['0 0 100px', '1 0 0']} color={'myGray.600'} fontWeight={'500'}>
|
||||
{t('common:support.wallet.subscription.Update extra expire')}
|
||||
</Box>
|
||||
<Flex
|
||||
justifyContent={'end'}
|
||||
alignItems={'center'}
|
||||
mt={1}
|
||||
w={'180px'}
|
||||
position={'relative'}
|
||||
>
|
||||
<MySelect
|
||||
bg={'myGray.50'}
|
||||
value={watchedMonth}
|
||||
size={'sm'}
|
||||
list={expireSelectorOptions}
|
||||
onChange={(val) => {
|
||||
setValueExtraPoints('month', val);
|
||||
// 当用户选择月份时,设置积分为该月份的最小值
|
||||
const minPoints = getMinPointsByMonth(val);
|
||||
setValueExtraPoints('points', minPoints);
|
||||
}}
|
||||
/>
|
||||
</Flex>
|
||||
</Flex>
|
||||
<Flex alignItems={'end'} fontSize={'sm'} h="36px">
|
||||
<Box flex={['0 0 100px', '1 0 0']} color={'myGray.600'} fontWeight={'500'}>
|
||||
{t('common:support.wallet.subscription.Update extra price')}
|
||||
</Box>
|
||||
<Flex
|
||||
justifyContent={'end'}
|
||||
alignItems={'center'}
|
||||
mt={1}
|
||||
w={'180px'}
|
||||
position={'relative'}
|
||||
fontWeight={500}
|
||||
fontSize={'20px'}
|
||||
>
|
||||
{`¥${(() => {
|
||||
const price = calculatePrice(extraPointsPrice, {
|
||||
type: 'points',
|
||||
points: watchedPoints
|
||||
});
|
||||
return Number.isNaN(price) ? 0 : price;
|
||||
})()}`}
|
||||
</Flex>
|
||||
</Flex>
|
||||
</Flex>
|
||||
<Box mt={'auto'}>
|
||||
<Button
|
||||
w={'100%'}
|
||||
h={'44px'}
|
||||
variant={'primaryGhost'}
|
||||
isLoading={isLoadingBuyExtraPoints}
|
||||
onClick={() => {
|
||||
const values = getValuesExtraPoints();
|
||||
const points = values.points || 1; // 如果为空,默认为1
|
||||
const month = values.month || 1;
|
||||
onclickBuyExtraPoints({ points, month });
|
||||
}}
|
||||
color={'primary.700'}
|
||||
>
|
||||
{t('common:support.wallet.Buy')}
|
||||
</Button>
|
||||
<HStack color={'blue.700'} mt={4}>
|
||||
<MyIcon name={'infoRounded'} w={'1rem'} />
|
||||
<Box fontSize={'sm'} fontWeight={'500'}>
|
||||
{t('common:support.wallet.subscription.Update extra ai points tips')}
|
||||
</Box>
|
||||
</HStack>
|
||||
</Box>
|
||||
<Button
|
||||
mt={6}
|
||||
w={'100%'}
|
||||
variant={'primaryGhost'}
|
||||
isLoading={isLoadingBuyExtraPoints}
|
||||
onClick={handleSubmitExtraPoints(onclickBuyExtraPoints)}
|
||||
color={'primary.700'}
|
||||
>
|
||||
{t('common:support.wallet.Buy')}
|
||||
</Button>
|
||||
</Box>
|
||||
</Flex>
|
||||
|
||||
{/* dataset */}
|
||||
<Flex
|
||||
flexDir="column"
|
||||
bg={'rgba(255, 255, 255, 0.90)'}
|
||||
px={'32px'}
|
||||
py={'24px'}
|
||||
borderRadius={'2xl'}
|
||||
borderWidth={'1px'}
|
||||
borderColor={'myGray.150'}
|
||||
boxShadow={'1.5'}
|
||||
w={['100%', '500px']}
|
||||
gap={4}
|
||||
>
|
||||
<Flex borderBottomWidth={'1px'} borderBottomColor={'myGray.200'} pb={1}>
|
||||
<Flex flexDir="column" gap={3} flex={'1 0 0'}>
|
||||
<Box fontSize={'lg'} fontWeight={'500'} color={'primary.700'}>
|
||||
{t('common:support.wallet.subscription.Extra dataset size')}
|
||||
</Box>
|
||||
<Box fontSize={['28px', '32px']} fontWeight={'bold'} color={'black'}>
|
||||
{`¥${extraDatasetPrice}/1000${t('common:support.wallet.subscription.Extra dataset unit')}`}
|
||||
</Box>
|
||||
<Box mt="auto" fontSize={'xs'} color={'myGray.600'} fontWeight={'500'}>
|
||||
{t('common:support.wallet.subscription.Extra dataset description')}
|
||||
</Box>
|
||||
</Flex>
|
||||
<MyIcon
|
||||
display={['none', 'block']}
|
||||
mt={'-30px'}
|
||||
transform={'translateX(20px)'}
|
||||
name={'support/bill/extraDatasetsize'}
|
||||
fill={'none'}
|
||||
/>
|
||||
</Flex>
|
||||
|
||||
<Flex flexDir="column" gap={4} h={'180px'} w={'100%'}>
|
||||
<Flex color={'myGray.900'}>
|
||||
<MyIcon
|
||||
mr={2}
|
||||
name={'support/bill/shoppingCart'}
|
||||
fontWeight={'500'}
|
||||
w={'16px'}
|
||||
color={'primary.600'}
|
||||
/>
|
||||
{t('common:support.wallet.buy_dataset_capacity')}
|
||||
</Flex>
|
||||
<Flex alignItems={'center'} fontSize={'sm'}>
|
||||
<Box flex={['0 0 100px', '1 0 0']} color={'myGray.600'} fontWeight={'500'}>
|
||||
{t('common:support.wallet.subscription.Dataset size')}
|
||||
</Box>
|
||||
<Flex
|
||||
justifyContent={'end'}
|
||||
alignItems={'center'}
|
||||
mt={1}
|
||||
w={'180px'}
|
||||
position={'relative'}
|
||||
>
|
||||
<MyNumberInput
|
||||
name="datasetSize"
|
||||
register={registerDatasetSize}
|
||||
defaultValue={1}
|
||||
max={10000}
|
||||
min={0}
|
||||
size={'sm'}
|
||||
/>
|
||||
<Box flexShrink={0} color={'myGray.600'}>
|
||||
{`X 1000${t('common:core.dataset.data.group')}`}
|
||||
</Box>
|
||||
</Flex>
|
||||
</Flex>
|
||||
<Flex alignItems={'center'} fontSize={'sm'}>
|
||||
<Box flex={['0 0 100px', '1 0 0']} color={'myGray.600'} fontWeight={'500'}>
|
||||
{t('common:support.wallet.subscription.Update extra expire')}
|
||||
</Box>
|
||||
<Flex
|
||||
justifyContent={'end'}
|
||||
alignItems={'center'}
|
||||
mt={1}
|
||||
w={'180px'}
|
||||
position={'relative'}
|
||||
>
|
||||
<MySelect
|
||||
bg={'myGray.50'}
|
||||
value={watchedDatasetMonth}
|
||||
size={'sm'}
|
||||
list={expireSelectorOptions}
|
||||
onChange={(val) => setValueDatasetSize('month', val)}
|
||||
/>
|
||||
</Flex>
|
||||
</Flex>
|
||||
<Flex alignItems={'end'} fontSize={'sm'} h="36px">
|
||||
<Box flex={['0 0 100px', '1 0 0']} color={'myGray.600'} fontWeight={'500'}>
|
||||
{t('common:support.wallet.subscription.Update extra price')}
|
||||
</Box>
|
||||
<Flex
|
||||
justifyContent={'end'}
|
||||
alignItems={'center'}
|
||||
mt={1}
|
||||
w={'180px'}
|
||||
position={'relative'}
|
||||
fontWeight={500}
|
||||
fontSize={'20px'}
|
||||
>
|
||||
{`¥${(() => {
|
||||
const price = calculatePrice(extraDatasetPrice, {
|
||||
type: 'dataset',
|
||||
size: watchedDatasetSize,
|
||||
month: watchedDatasetMonth
|
||||
});
|
||||
return Number.isNaN(price) ? 0 : price;
|
||||
})()}`}
|
||||
</Flex>
|
||||
</Flex>
|
||||
</Flex>
|
||||
<Box mt={'auto'}>
|
||||
<Button
|
||||
w={'100%'}
|
||||
h={'44px'}
|
||||
variant={'primaryGhost'}
|
||||
isLoading={isLoadingBuyDatasetSize}
|
||||
onClick={handleSubmitDatasetSize(onclickBuyDatasetSize)}
|
||||
color={'primary.700'}
|
||||
>
|
||||
{t('common:support.wallet.Buy')}
|
||||
</Button>
|
||||
<HStack color={'blue.700'} mt={4}>
|
||||
<MyIcon name={'infoRounded'} w={'1rem'} />
|
||||
<Box fontSize={'sm'} fontWeight={'500'}>
|
||||
{t('common:support.wallet.subscription.Update extra dataset tips')}
|
||||
</Box>
|
||||
</HStack>
|
||||
</Box>
|
||||
</Flex>
|
||||
</Grid>
|
||||
|
||||
{!!qrPayData && <QRCodePayModal onSuccess={onPaySuccess} {...qrPayData} />}
|
||||
|
@@ -48,7 +48,7 @@ const PriceBox = () => {
|
||||
<Box fontWeight={'600'} color={'myGray.900'} fontSize={['24px', '36px']}>
|
||||
{t('common:support.wallet.subscription.Sub plan')}
|
||||
</Box>
|
||||
<Box mt={8} mb={10} fontWeight={'500'} color={'myGray.600'} fontSize={'md'}>
|
||||
<Box fontWeight={'500'} color={'myGray.600'} fontSize={'md'}>
|
||||
{t('common:support.wallet.subscription.Sub plan tip', {
|
||||
title: feConfigs?.systemTitle
|
||||
})}
|
||||
|
Reference in New Issue
Block a user